custom_tabbarview

This package is almost identical to the TabBarView API in the Flutter SDK, but with enhanced customization capabilities.

Presets

fade stack carousel
toss1 toss2

Feature

  1. It's a direct clone of TabBarView from the Flutter SDK, so more than 95% of the codebase is identical and reliable.
  2. The widgets in children(tabs) are all built lazily, with keepAlive behavior as needed. lazy_build
  3. Transition animations are 100% customizable based on transition rate.
  4. There are plenty of presets to get you started quickly, and hints for customization.

Migration guide

from TabBarView

If you were previously using TabBarView, you can follow these steps to migrate.

  1. Change from TabBarView to CustomTabBarView

If you want to use the main feature -- .builder in addition, you can follow the steps below.

  1. Rename chindren to tabs.
  2. Implement builder type of CustomTabBarViewBuilder or just use other named constructor.

CustomTabBarViewBuilder

The type of builder method used globally in CustomTabBarView.

It returns a Widget and takes the following arguments:

  • context: BuildContext for the widget.
  • pageController: A PageController for PageView that internally implements TabBarView.
  • childrenWithKey: The children or tabs passed in.
    However, the implementation of TabBarView temporarily changes the order of the child widgets on transition.
  • index: The index of the widget currently being displayed in the TabBarView.

Important

You can get the child that match the TabController with childrenWithKey[index].

Example

class HomeTab extends StatefulWidget {
  const HomeTab({super.key});

  @override
  State<HomeTab> createState() => _HomeTabState();
}

class _HomeTabState extends State<HomeTab> with SingleTickerProviderStateMixin {
  late TabController _tabController;
  final List<Widget> _children = [
    const HomePage(),
    const Page1(),
    const Page2(),
    const Page3(),
    const Page4(),
  ];

  @override
  void initState() {
    super.initState();
    _tabController = TabController(
      length: 5,
      initialIndex: 0,
      vsync: this,
    );
  }

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

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.sizeOf(context).width;

    return Scaffold(
      appBar: AppBar(
        title: const Text('CustomTabBarView Demo'),
      ),
      backgroundColor: Colors.white,
      body: CustomTabBarView.builder(
        controller: _tabController,
        physics: const PageScrollPhysics(),
        dragStartBehavior: DragStartBehavior.down,
        tabs: _children,
        builder: (context, pageController, childrenWithKey, index) {
          return AnimatedBuilder(
            animation: pageController,
            builder: (context, child) {
              final page =
                  pageController.page ?? pageController.initialPage.toDouble();
              final offset = (page - index) * pageController.viewportFraction;

              final dx = offset * width * 0.8;
              final scale = 1 - offset.abs() * 0.1;
              final opacity = 1 - offset.abs() * 2;

              return Opacity(
                opacity: opacity.clamp(0.0, 1.0),
                child: Transform.scale(
                  scale: scale,
                  child:
                      Transform.translate(offset: Offset(dx, 0), child: child),
                ),
              );
            },
            child: childrenWithKey[index],
          );
        },
      ),
      bottomNavigationBar: SafeArea(
        child: Transform.flip(
          flipY: true,
          child: SizedBox(
            height: 60,
            child: TabBar(
              controller: _tabController,
              isScrollable: false,
              labelColor: Theme.of(context).primaryColorDark,
              indicatorColor: Theme.of(context).primaryColorDark,
              labelStyle: const TextStyle(fontSize: 10),
              tabs: [
                Transform.flip(
                  flipY: true,
                  child: const Tab(icon: Icon(Icons.home), text: '홈'),
                ),
                Transform.flip(
                  flipY: true,
                  child: const Tab(icon: Icon(Icons.one_k), text: 'Page 1'),
                ),
                Transform.flip(
                  flipY: true,
                  child: const Tab(icon: Icon(Icons.two_k), text: 'Page 2'),
                ),
                Transform.flip(
                  flipY: true,
                  child: const Tab(icon: Icon(Icons.three_k), text: 'Page 3'),
                ),
                Transform.flip(
                  flipY: true,
                  child: const Tab(icon: Icon(Icons.four_k), text: 'Page 4'),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Libraries

custom_tabbarview