DEV Community

Cover image for Nested Scroll View Flutter
Kunal Jain for CodeDecoders

Posted on • Updated on • Originally published at dev.to

Nested Scroll View Flutter

Hello guys, this blog post is a part of a video series we are started to upload on YouTube.
Flutter News App (Frontend to Backend)

Here is the video:-

In this blog post, we will create the body of the homepage using Nested Scroll View.
Alt Text

Now in the project, We will create a new folder named screens/home in which create a homepage.dart a file.

Now let's create a StateFull Widget named HomePage().

HomePage() would return a NestedScrollView().

Now we replace the Container() in body of Home() from HomePage():-

In NestedScrollView, there is a parameter, headerSliverBuilder:-

headerSliverBuilder: (context, value) {
        return [
        ];
      },

In return of headerSliverBuilder, we will pass the Sliver App Bar:-

SliverToBoxAdapter(
           child: Padding(
              padding: const EdgeInsets.fromLTRB(25, 10, 25, 25),
              child: Align(
                alignment: Alignment.centerLeft,
                child: Text(
                  "Top News Updates",
                  textAlign: TextAlign.left,
                  style: TextStyle(
                    fontFamily: "Times",
                    fontSize: 34,
                    fontWeight: FontWeight.w700,
                  ),
                ),
              ),
            ),
          ),

Now we will create categories list. For that, we will create a folder named as model in which we create categories.dart as a file.
Now we will create a class named CategoryModel.In which we pass use variable name and imageUrl and we will create the constructor of the class.

class CategoryModel{
  final name,imageUrl;
  CategoryModel({this.name, this.imageUrl});
}

Then we will create the list of CategoryModel.

List<CategoryModel> categories = [
  CategoryModel(name: "Top stories", imageUrl: "assets/images/categories/topnews.jpg"),
  CategoryModel(name: "India", imageUrl: "assets/images/categories/india.jpg"),
  CategoryModel(name: "World", imageUrl: "assets/images/categories/world.jpg"),
  CategoryModel(name: "Business", imageUrl: "assets/images/categories/business.jpg"),
  CategoryModel(name: "Sports", imageUrl: "assets/images/categories/sports.jpg"),
  CategoryModel(name: "Cricket", imageUrl: "assets/images/categories/cricket.jpg"),
  CategoryModel(name: "Tech", imageUrl: "assets/images/categories/tech.jpg"),
  CategoryModel(name: "Education", imageUrl: "assets/images/categories/education.jpg"),
  CategoryModel(name: "Entertainment", imageUrl: "assets/images/categories/entertainment.jpg"),
  CategoryModel(name: "Music", imageUrl: "assets/images/categories/music.jpg"),
  CategoryModel(name: "Lifestyle", imageUrl: "assets/images/categories/lifestyle.jpg"),
  CategoryModel(name: "Health and Fitness", imageUrl: "assets/images/categories/health_fitness.jpg"),
  CategoryModel(name: "Fashion", imageUrl: "assets/images/categories/fashion_trends.jpg"),
  CategoryModel(name: "Art and Culture", imageUrl: "assets/images/categories/art_culture.jpg"),
  CategoryModel(name: "Travel", imageUrl: "assets/images/categories/travel.jpg"),
  CategoryModel(name: "Books", imageUrl: "assets/images/categories/books.jpg"),
  CategoryModel(name: "Real Estate", imageUrl: "assets/images/categories/realestate.jpg"),
  CategoryModel(name: "Its Viral", imageUrl: "assets/images/categories/its_viral.jpg"),
];

Now go back to homepage.dart.In return of headerSliverBuilder, we will create our TabBar.

Now for TabBar And Nested Scroll View, we will create the controller and integer:-

ScrollController _scrollController;
TabController _tabController;
int currentIndex = 0;

Now we will create the functions named as changePage and _smoothScrollToTop:-

void changePage(int index) {
    setState(() {
      currentIndex = index;
    });
  }

_smoothScrollToTop() {
    _scrollController.animateTo(
      0,
      duration: Duration(microseconds: 300),
      curve: Curves.ease,
    );
  }

Now we will create initState of HomePage()

@override
  void initState() {
    // TODO: implement initState
    super.initState();
    _scrollController = ScrollController();
    _tabController = TabController(length: categories.length, vsync: this);
    _tabController.addListener(_smoothScrollToTop);
 }

In TabController, there is parameter vsync where we use this. Now for this, we have to use SingleTickerProviderStateMixin Here:-

class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {

Now we will create the dispose of HomePage()

@override
  void dispose() {
    super.dispose();
    _tabController.dispose();
    _scrollController.dispose();
  }

In TabBar, there is a parameter tabs in which we will pass the List.generate and give the list of CategoryModel as created above.

SliverToBoxAdapter(
            child: Container(
              padding: EdgeInsets.only(left: 25),
              alignment: Alignment.centerLeft,
              child: TabBar(
                  labelPadding: EdgeInsets.only(right: 15),
                  indicatorSize: TabBarIndicatorSize.label,
                  controller: _tabController,
                  isScrollable: true,
                  indicator: UnderlineTabIndicator(),
                  labelColor: Colors.black,
                  labelStyle: TextStyle(
                      fontFamily: "Avenir",
                      fontSize: 19,
                      fontWeight: FontWeight.bold),
                  unselectedLabelColor: Colors.black45,
                  unselectedLabelStyle: TextStyle(
                      fontFamily: "Avenir",
                      fontSize: 18,
                      fontWeight: FontWeight.normal),
                  tabs: List.generate(categories.length,
                      (index) => Text(categories[index].name))),
            ),
          ),

Now in NestedScrollView, there is a parameter body.

But before that, we will create a new folder in lib as reusable in which we will create a new file named custom_cards.dart.

Now in custom_card.dart, we will create a Stateless Widget named HomePageCard.This will be our Reusable Widget.

class HomePageCard extends StatelessWidget {
  final imageUrl, title, subtitle, time;

  const HomePageCard(
      {Key key,
      this.imageUrl = "assets/cardimage.jpg",
      this.title =
          "Watch: Gameplay for the first 13 games optimised for Xbox Series X",
      this.time = "07 May  07:19",
      this.subtitle =
          "Microsoft showcased 13 games, with their gameplay trailers, that will come to Xbox Series X with optimisations."})
      : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(top: 15),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            height: 203,
            width: MediaQuery.of(context).size.width,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10),
              border: Border.all(
                color: Color(0xff707070),
                width: 1,
              ),
              image: DecorationImage(
                  image: AssetImage(imageUrl), fit: BoxFit.fill),
            ),
            child: Align(
              alignment: Alignment.bottomCenter,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  Container(
                    width: MediaQuery.of(context).size.width,
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(11),
                      color: Colors.black.withOpacity(0.33),
                    ),
                    padding: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
                    child: Center(
                      child: Text(
                        subtitle,
                        style: TextStyle(
                            fontFamily: "Avenir",
                            fontSize: 16,
                            color: Colors.white),
                        maxLines: 3,
                        overflow: TextOverflow.fade,
                      ),
                    ),
                  )
                ],
              ),
            ),
          ),
          SizedBox(
            height: 10,
          ),
          Text(time,
              style: TextStyle(
                  fontFamily: "Times", fontSize: 13, color: Color(0xff8a8989))),
          SizedBox(
            height: 7,
          ),
          Text(title,
              style: TextStyle(
                  fontFamily: "League",
                  fontSize: 23,
                  fontWeight: FontWeight.bold)),
        ],
      ),
    );
  }
}

Now in the body of NestedScrollView, we will pass List.generate in which we will return the ListView.builder in which we will return HomePageCard and itemCount will be static.

body: Container(
          child: TabBarView(controller: _tabController,children: List.generate(categories.length, (index) {
            return ListView.builder(itemCount: 10,itemBuilder: (context, index) {
              return HomePageCard();
            },
            padding: EdgeInsets.symmetric(horizontal: 25),
            );
          })),
        )

Now last see the final output:-
Alt Text

Github Source Code Link:-



Branch: Part--3--NestedScrollView

Top comments (0)