I implemented a basic TabBar and TabBarView with a DefaultTabController, see code below.
class MyApp2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: BOTTOM_TABS,
child: Scaffold(
appBar: AppBar(title: const Text('Bottom App Bar')),
body: _tabBarView(),
bottomNavigationBar: _bottomTabBar(),
),
);
}
_tabBarView() {
return TabBarView(
physics: NeverScrollableScrollPhysics(),
children: [
Container(
color: Colors.blue,
),
Container(
color: Colors.orange,
),
Container(
color: Colors.lightGreen,
),
Container(
color: Colors.red,
),
],
);
}
_bottomTabBar() {
return TabBar(
tabs: [
Tab(
icon: new Icon(Icons.home),
),
Tab(
icon: new Icon(Icons.public),
),
Tab(
icon: new Icon(Icons.group),
),
Tab(
icon: new Icon(Icons.person),
)
],
);
}
}
Works great! Now what I want to do is change the animation between the two tabs from the default animation. But I can't find an easy way to do that.
After a bit of research it seems like I need to use a custom TabController and somehow use its animateTo method. To me that seems like a pretty big change just to change the animation. What I wonder is if that is the correct way or if I am missing some easier way to just change the default animation between the tabviews?
If someone could give me some good resources to point me in the right direction I'd greatly appreciate it.
You need to get the TabBar controller and call its animateTo() method from the button onPressed() handle. Save this answer.
AnimatedBuilder is useful for more complex widgets that wish to include an animation as part of a larger build function. To use AnimatedBuilder, simply construct the widget and pass it a builder function. For simple cases without additional state, consider using AnimatedWidget.
The selected tab's index can be changed with animateTo. A stateful widget that builds a TabBar or a TabBarView can create a TabController and share it directly. When the TabBar and TabBarView don't have a convenient stateful ancestor, a TabController can be shared by providing a DefaultTabController inherited widget.
This is not hard, just use TabController (to do so you need to use SingleTickerProviderStateMixin ) and AnimatedBuilder.
class MyApp2 extends StatefulWidget {
@override
_MyApp2State createState() => _MyApp2State();
}
class _MyApp2State extends State<MyApp2> with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void initState() {
_tabController = TabController(length: 4, vsync: this);
super.initState();
}
_tabBarView() {
return AnimatedBuilder(
animation: _tabController.animation,
builder: (BuildContext context, snapshot) {
return Transform.rotate(
angle: _tabController.animation.value * pi,
child: [
Container(
color: Colors.blue,
),
Container(
color: Colors.orange,
),
Container(
color: Colors.lightGreen,
),
Container(
color: Colors.red,
),
][_tabController.animation.value.round()],
);
},
);
}
_bottomTabBar() {
return TabBar(
controller: _tabController,
labelColor: Colors.black,
tabs: [
Tab(
icon: new Icon(Icons.home),
),
Tab(
icon: new Icon(Icons.public),
),
Tab(
icon: new Icon(Icons.group),
),
Tab(
icon: new Icon(Icons.person),
)
],
);
}
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(title: const Text('Bottom App Bar')),
body: _tabBarView(),
bottomNavigationBar: _bottomTabBar(),
),
);
}
}
I don't know if you want to completely change the animation.
But if you just need some customization, did you try to use a TabController
instead of a DefaultTabController
?
You just need to pass the tabController
as an arg to the TabBar
& TabBarView
.
To customize the animation with the tabController
, you should specify an Animation for the tabController
and also specify the curve and duration with the animateTo
function of the tabController
.
https://api.flutter.dev/flutter/material/TabController/animateTo.html https://api.flutter.dev/flutter/material/TabController-class.html
Screenshot (Null safe):
Code:
If you want fine-grained control, you can make use of the AnimationController
.
class _MyPageState extends State<MyPage> with TickerProviderStateMixin {
late final TabController _tabController;
late final AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(milliseconds: 400),
value: 1,
);
_tabController = TabController(
length: 3,
vsync: this,
)..addListener(() {
if (_tabController.indexIsChanging) {
setState(() => _controller.forward(from: 0.5));
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ScaleTransition(
scale: _controller,
child: [
Container(color: Colors.red),
Container(color: Colors.green),
Container(color: Colors.blue),
][_tabController.index],
),
bottomNavigationBar: TabBar(
controller: _tabController,
tabs: [
Tab(child: Text('Red')),
Tab(child: Text('Green')),
Tab(child: Text('Blue')),
],
),
);
}
}
Disable animation between flutter tabs by setting animation duration to zero like this
tabController = TabController(
animationDuration: Duration.zero,
length: 4, vsync: this, initialIndex: 0);
Thank me later.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With