vertical_scroll_tabbar 0.0.1 copy "vertical_scroll_tabbar: ^0.0.1" to clipboard
vertical_scroll_tabbar: ^0.0.1 copied to clipboard

Vertical Scroll Tabbar

example/lib/main.dart

import 'dart:async';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(),
      home: Scaffold(
        body: SafeArea(
          child: VerticalScrollTabbar(
            title: 'Flutter Demo Home Page',
            tabs: const [
              Tab(
                text: 'A',
              ),
              Tab(
                text: 'B',
              ),
              Tab(
                text: 'C',
              ),
              Tab(
                text: 'D',
              ),
              Tab(
                text: 'E',
              ),
            ],
            children: [
              Column(
                key: GlobalKey(),
                children: [...a],
              ),
              Column(key: GlobalKey(), children: [...b]),
              Column(
                key: GlobalKey(),
                children: [...c],
              ),
              Column(
                key: GlobalKey(),
                children: [...b],
              ),
              Column(
                key: GlobalKey(),
                children: [...a],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class VerticalScrollTabbar extends StatefulWidget {
  const VerticalScrollTabbar(
      {super.key,
        required this.title,
        required this.children,
        required this.tabs});

  final String title;
  final List<Widget> children;
  final List<Tab> tabs;

  @override
  State<VerticalScrollTabbar> createState() => _VerticalScrollTabbarState();
}

class _VerticalScrollTabbarState extends State<VerticalScrollTabbar>
    with SingleTickerProviderStateMixin {
  ScrollController scrollController = ScrollController();
  List indexList = [];
  TabController? tabController;
  bool mutex = false;
  Timer? timer;

  @override
  void initState() {
    tabController = TabController(
      length: widget.tabs.length,
      vsync: this,
    );
    tabController?.addListener(() {
      if (tabController?.animation?.isCompleted ?? true) {
        timer?.cancel();
        timer = Timer(const Duration(milliseconds: 500), () {
          mutex = false;
        });
      }
    });

    scrollController.addListener(() {
      if (mutex) return;

      for (var index = indexList.length - 1; index >= 0; index--) {
        if (scrollController.offset >= indexList[index]) {
          tabController?.animateTo(index);
          return;
        }
      }
    });
    super.initState();
  }

  @override
  void dispose() {
    tabController?.dispose();
    scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TabBar(
          tabs: [...widget.tabs],
          controller: tabController,
          onTap: (index) {
            mutex = true;
            scrollController.animateTo(indexList[index],
                duration: const Duration(milliseconds: 500),
                curve: Curves.easeIn);
          },
        ),
        Expanded(
          child: ListWidget(
              scrollController: scrollController,
              onIndexInit: (indexList) {
                this.indexList.addAll(indexList);
              },
              children: [
                ...widget.children,
              ]),
        ),
      ],
    );
  }
}

class ListWidget extends StatefulWidget {
  const ListWidget({
    Key? key,
    required this.children,
    required this.scrollController,
    required this.onIndexInit,
  }) : super(key: key);

  final List<Widget> children;
  final ScrollController scrollController;
  final Function(List indexList) onIndexInit;

  @override
  State<ListWidget> createState() => _ListWidgetState();
}

class _ListWidgetState extends State<ListWidget> {
  final List indexes = [];

  @override
  void initState() {
    WidgetsBinding.instance.endOfFrame.then((value) {
      final ancestor = context.findRenderObject();

      for (var element in widget.children) {
        assert(element.key != null && element.key is GlobalKey);

        final res = ((element.key as GlobalKey)
            .currentContext
            ?.findRenderObject() as RenderBox)
            .localToGlobal(Offset.zero, ancestor: ancestor);

        print(res.dy);

        indexes.add(res.dy);
      }

      widget.onIndexInit(indexes);
    });

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: SingleChildScrollView(
            controller: widget.scrollController,
            child: Column(children: [
              ...widget.children,
            ]),
          ),
        ),
      ],
    );
  }
}

List<Widget> a = [
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.red,
  ),
];

List<Widget> b = [
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.blue,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.blue,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.blue,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.blue,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.blue,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.blue,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.blue,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.blue,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.blue,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.blue,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.blue,
  ),
];

List<Widget> c = [
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.green,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.green,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.green,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.green,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.green,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.green,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.green,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.green,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.green,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.green,
  ),
  Container(
    margin: const EdgeInsets.all(20),
    height: 100,
    width: 100,
    color: Colors.green,
  ),
];
12
likes
0
pub points
71%
popularity

Publisher

unverified uploader

Vertical Scroll Tabbar

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on vertical_scroll_tabbar