Flutter Scrollable List Tab Scroller

Customizable Flutter widget which synchronize ScrollView with tabs.

Create custom tabs which synchronize with inner ScrollView. The tabs follow the index of scroll view and vice-versa.

Installation

Add dependency for package on your pubspec.yaml:

dependencies:
 scrollable_list_tab_scroller: <latest>

Example

import 'package:flutter/material.dart';
import 'package:scrollable_list_tab_scroller/scrollable_list_tab_scroller.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: 'Scrollable List Tab Scroller',
   theme: ThemeData(
     primarySwatch: Colors.blue,
   ),
   home: MyHomePage(title: 'Scrollable List Tab Scroller'),
 );
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);

final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
final data = {
 "Category A": [
   "Item 1 (A)",
   "Item 2 (A)",
   "Item 3 (A)",
   "Item 4 (A)",
 ],
 "Category B": [
   "Item 1 (B)",
   "Item 2 (B)",
 ],
 "Category C": [
   "Item 1 (C)",
   "Item 2 (C)",
   "Item 3 (C)",
   "Item 4 (C)",
   "Item 5 (C)",
 ],
 "Category D": [
   "Item 1 (D)",
   "Item 2 (D)",
   "Item 3 (D)",
   "Item 4 (D)",
   "Item 5 (D)",
   "Item 6 (D)",
   "Item 7 (D)",
   "Item 8 (D)",
   "Item 9 (D)",
 ],
};

@override
Widget build(BuildContext context) {
 return Scaffold(
     appBar: AppBar(
       title: Text(widget.title),
     ),
     body: ScrollableListTabScroller(
       tabBuilder: (BuildContext context, int index, bool active) => Text(
         data.keys.elementAt(index),
         style: !active
             ? null
             : TextStyle(fontWeight: FontWeight.bold, color: Colors.green),
       ),
       itemCount: data.length,
       itemBuilder: (BuildContext context, int index) => Column(
         children: [
           Text(
             data.keys.elementAt(index),
             style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
           ),
           ...data.values
               .elementAt(index)
               .asMap()
               .map(
                 (index, value) => MapEntry(
                   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(value),
                   ),
                 ),
               )
               .values
         ],
       ),
     ));
}
}

GitHub

View Github