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

![]() |
![]() |
![]() |
fade | stack | carousel |
![]() |
![]() |
|
toss1 | toss2 |
- It's a direct clone of TabBarView from the Flutter SDK, so more than 95% of the codebase is identical and reliable.
- The widgets in children(tabs) are all built lazily, with keepAlive behavior as needed.
- Transition animations are 100% customizable based on transition rate.
- There are plenty of presets to get you started quickly, and hints for customization.
If you were previously using TabBarView, you can follow these steps to migrate.
- Change from
TabBarView
toCustomTabBarView
.
If you want to use the main feature -- .builder
in addition, you can follow the steps below.
- Rename
chindren
totabs
. - Implement
builder
type ofCustomTabBarViewBuilder
or just use other named constructor.
If you were previously using CustomTabBarView.builder, you can follow these steps to migrate.
- Change from
builder
constructor tocustom
. - Change from
builder
parameter tobuilderDelegate
and put previous builder function into builderDelegate class.
// AS-IS
CustomTabBarView.builder(
controller: controller,
tabs: tabs,
builder: (context, pageController, childrenWithKey, index) {
return childrenWithKey[index];
}
)
// TO-BE
CustomTabBarView.custom(
controller: controller,
tabs: tabs,
builderDelegate: CustomTabBarViewCustomBuilderDelegate(
(context, pageController, childrenWithKey, index) {
return childrenWithKey[index];
},
),
)
The type of builder method used globally in CustomTabBarView.
It returns a Widget and takes the following arguments:
context
:BuildContext
for the widget.offset
: The offset value for each widget in the TabBarView. 1: left / 0: center / -1: rightwidget
: Each child widget of tabs.
The type of custom builder method used globally in CustomTabBarView.
It returns a Widget and takes the following arguments:
context
:BuildContext
for the widget.pageController
: APageController
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]
.
Except for the default constructor, the code snippet below performs the same behavior.
CustomTabBarView(
controller: _tabController,
children: _children,
)
CustomTabBarView.builder(
controller: _tabController,
tabs: _children,
builder: (context, offset, child) {
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),
),
);
},
)
CustomTabBarView.custom(
controller: _tabController,
physics: const PageScrollPhysics(),
dragStartBehavior: DragStartBehavior.down,
tabs: _children,
builderDelegate: CustomTabBarViewBuilderDelegate(
(context, offset, child) {
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),
),
);
},
),
)
CustomTabBarView.custom(
controller: _tabController,
tabs: _children,
builderDelegate: CustomTabBarViewCustomBuilderDelegate(
(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],
);
},
),
)
CustomTabBarView.carousel(
controller: _tabController,
physics: const PageScrollPhysics(),
dragStartBehavior: DragStartBehavior.down,
tabs: _children,
)