DEV Community

Cover image for Nested Scroll View Flutter
Kunal Jain for CodeDecoders

Posted on • Edited 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 [
        ];
      },
Enter fullscreen mode Exit fullscreen mode

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,
                  ),
                ),
              ),
            ),
          ),
Enter fullscreen mode Exit fullscreen mode

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});
}
Enter fullscreen mode Exit fullscreen mode

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"),
];
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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,
    );
  }
Enter fullscreen mode Exit fullscreen mode

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);
 }
Enter fullscreen mode Exit fullscreen mode

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 {
Enter fullscreen mode Exit fullscreen mode

Now we will create the dispose of HomePage()

@override
  void dispose() {
    super.dispose();
    _tabController.dispose();
    _scrollController.dispose();
  }
Enter fullscreen mode Exit fullscreen mode

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))),
            ),
          ),
Enter fullscreen mode Exit fullscreen mode

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)),
        ],
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

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),
            );
          })),
        )
Enter fullscreen mode Exit fullscreen mode

Now last see the final output:-
Alt Text

Github Source Code Link:-






Branch: Part--3--NestedScrollView

Top comments (0)