flutterflutter-layoutnestedscrollview

How to create a tabbar that sync with a widget scroll in flutter?


Basically what I want to accomplish here is to have a horizontal list of categories(could be TabBar) and a vertical list of the categories with items list in each category.

And when you click on a category it should scroll to a position in the vertical list of categories. And when you scroll the vertical list, the active category at the top should also update the current active category.

I've seen this function in the FoodPanda app but I am not able to replicate it.

Any suggestions on how can I accomplish this functionality?

Here's the screenshot of the UI. enter image description here


Solution

  • You can copy paste run full code below
    You can use package https://pub.dev/packages/scrollable_list_tabview
    code snippet

    body: ScrollableListTabView(
            tabHeight: 48,
            bodyAnimationDuration: const Duration(milliseconds: 150),
            tabAnimationCurve: Curves.easeOut,
            tabAnimationDuration: const Duration(milliseconds: 200),
            tabs: [
              ScrollableListTab(
                  tab: ListTab(
                      label: Text('Vegetables'),
                      icon: Icon(Icons.group),
                      showIconOnList: false),
                  body: ListView.builder(
                    shrinkWrap: true,
                    physics: NeverScrollableScrollPhysics(),
                    itemCount: 10,
                    itemBuilder: (_, index) => ListTile(
                      leading: Container(
                        height: 40,
                        width: 40,
                        decoration: BoxDecoration(
                            shape: BoxShape.circle, color: Colors.grey),
                        alignment: Alignment.center,
                        child: Text(index.toString()),
                      ),
                      title: Text('Vegetables element $index'),
                    ),
                  )),
              ScrollableListTab(
                  tab: ListTab(label: Text('Fruits'), icon: Icon(Icons.add)),
                  body: ListView.builder(
                    shrinkWrap: true,
                    physics: NeverScrollableScrollPhysics(),
    

    working demo

    enter image description here

    full code

    import 'package:flutter/material.dart';
    import 'package:scrollable_list_tabview/scrollable_list_tabview.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(title: 'Flutter ScrollableListTabView Example'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: ScrollableListTabView(
            tabHeight: 48,
            bodyAnimationDuration: const Duration(milliseconds: 150),
            tabAnimationCurve: Curves.easeOut,
            tabAnimationDuration: const Duration(milliseconds: 200),
            tabs: [
              ScrollableListTab(
                  tab: ListTab(
                      label: Text('Vegetables'),
                      icon: Icon(Icons.group),
                      showIconOnList: false),
                  body: ListView.builder(
                    shrinkWrap: true,
                    physics: NeverScrollableScrollPhysics(),
                    itemCount: 10,
                    itemBuilder: (_, index) => ListTile(
                      leading: Container(
                        height: 40,
                        width: 40,
                        decoration: BoxDecoration(
                            shape: BoxShape.circle, color: Colors.grey),
                        alignment: Alignment.center,
                        child: Text(index.toString()),
                      ),
                      title: Text('Vegetables element $index'),
                    ),
                  )),
              ScrollableListTab(
                  tab: ListTab(label: Text('Fruits'), icon: Icon(Icons.add)),
                  body: ListView.builder(
                    shrinkWrap: true,
                    physics: NeverScrollableScrollPhysics(),
                    itemCount: 10,
                    itemBuilder: (_, index) => ListTile(
                      leading: Container(
                        height: 40,
                        width: 40,
                        decoration: BoxDecoration(
                            shape: BoxShape.circle, color: Colors.grey),
                        alignment: Alignment.center,
                        child: Text(index.toString()),
                      ),
                      title: Text('Fruits element $index'),
                    ),
                  )),
              ScrollableListTab(
                  tab: ListTab(label: Text('Meat'), icon: Icon(Icons.group)),
                  body: ListView.builder(
                    shrinkWrap: true,
                    physics: NeverScrollableScrollPhysics(),
                    itemCount: 10,
                    itemBuilder: (_, index) => ListTile(
                      leading: Container(
                        height: 40,
                        width: 40,
                        decoration: BoxDecoration(
                            shape: BoxShape.circle, color: Colors.grey),
                        alignment: Alignment.center,
                        child: Text(index.toString()),
                      ),
                      title: Text('Meat element $index'),
                    ),
                  )),
              ScrollableListTab(
                  tab: ListTab(
                      label: Text('Herbs&Spices'), icon: Icon(Icons.subject)),
                  body: GridView.builder(
                    shrinkWrap: true,
                    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                        crossAxisCount: 2),
                    physics: NeverScrollableScrollPhysics(),
                    itemCount: 10,
                    itemBuilder: (_, index) => Card(
                      child: Center(child: Text('Herbs&Spices element $index')),
                    ),
                  )),
              ScrollableListTab(
                  tab: ListTab(
                      label: Text('Egg'),
                      icon: Icon(Icons.subject),
                      showIconOnList: true),
                  body: GridView.builder(
                    shrinkWrap: true,
                    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                        crossAxisCount: 2),
                    physics: NeverScrollableScrollPhysics(),
                    itemCount: 10,
                    itemBuilder: (_, index) => Card(
                      child: Center(child: Text('Egg element $index')),
                    ),
                  )),
            ],
          ),
        );
      }
    }