Button Tab Bar In Flutter
Using this flutter tutorial you can create the button tab bar in flutter
when you develop any application in flutter and you need to design button tab bar in flutter so this flutter tutorial will be very helpful for you. in button tab bar tutorial all the buttons that you design will be display in a form of tab as you can see in the screenshot(button tab bar : car,transit)
this types of tab bar is common in iOS but now you can design it in android using flutter.i know it is very difficult to understand so all the code is commented with its use so you can easily understand. it is important to control the animation of your whole app.
i use scaffold for the body of the app. each button has its own key so later we can get the button position using its index. When a button is pressed, the Tab Change and Scroll animations are triggered and the current index is set.
here is a full source code with output.study it for get further information about button tab bar in flutter
Screenshot :

buttons_tabbar.dart
import 'package:flutter/material.dart'; // Default values from the Flutter's TabBar. const double _kTabHeight = 46.0; const double _kTextAndIconTabHeight = 72.0; class ButtonsTabBar extends StatefulWidget implements PreferredSizeWidget { ButtonsTabBar({ Key key, @required this.tabs, this.controller, this.duration = 250, this.backgroundColor = Colors.blueAccent, this.unselectedBackgroundColor = Colors.grey, this.labelStyle, this.unselectedLabelStyle, this.physics, this.contentPadding, this.buttonMargin, this.labelSpacing = 4.0, this.radius = 7.0, }) : super(key: key); final List<Widget> tabs; final TabController controller; final int duration; final Color backgroundColor; final Color unselectedBackgroundColor; final TextStyle labelStyle; final TextStyle unselectedLabelStyle; final ScrollPhysics physics; final EdgeInsets contentPadding; final EdgeInsets buttonMargin; final double labelSpacing; final double radius; @override Size get preferredSize { for (Widget item in tabs) { if (item is Tab) { final Tab tab = item; if (tab.text != null && tab.icon != null) return Size.fromHeight(_kTextAndIconTabHeight); } } return Size.fromHeight(_kTabHeight); } @override _ButtonsTabBarState createState() => _ButtonsTabBarState(); } class _ButtonsTabBarState extends State<ButtonsTabBar> with TickerProviderStateMixin { TabController _controller; ScrollController _scrollController = new ScrollController(); ScrollPhysics _scrollPhysics; AnimationController _animationController; List<GlobalKey> _tabKeys; GlobalKey _tabsContainerKey = GlobalKey(); Animation<Color> _colorTweenForegroundActivate; Animation<Color> _colorTweenForegroundDeactivate; Animation<Color> _colorTweenBackgroundActivate; Animation<Color> _colorTweenBackgroundDeactivate; Color _unselectedForegroundColor; Color _foregroundColor; TextStyle _unselectedLabelStyle; TextStyle _labelStyle; EdgeInsets _contentPadding; EdgeInsets _buttonMargin; int _currentIndex = 0; int _prevIndex = -1; int _aniIndex = 0; double _prevAniValue = 0; @override void initState() { super.initState(); _tabKeys = widget.tabs.map((Widget tab) => GlobalKey()).toList(); _scrollPhysics = widget.physics ?? BouncingScrollPhysics(); _unselectedLabelStyle = widget.unselectedLabelStyle ?? TextStyle(color: Colors.black); _labelStyle = widget.labelStyle ?? TextStyle(color: Colors.white); _foregroundColor = _labelStyle.color ?? Colors.white; _unselectedForegroundColor = _unselectedLabelStyle.color ?? Colors.black; _contentPadding = widget.contentPadding ?? EdgeInsets.all(4); _buttonMargin = widget.buttonMargin ?? EdgeInsets.all(4); _animationController = AnimationController( vsync: this, duration: Duration(milliseconds: widget.duration)); _colorTweenBackgroundActivate = ColorTween( begin: widget.unselectedBackgroundColor, end: widget.backgroundColor) .animate(_animationController); _colorTweenBackgroundDeactivate = ColorTween( begin: widget.backgroundColor, end: widget.unselectedBackgroundColor) .animate(_animationController); _colorTweenForegroundActivate = ColorTween(begin: _unselectedForegroundColor, end: _foregroundColor) .animate(_animationController); _colorTweenForegroundDeactivate = ColorTween(begin: _foregroundColor, end: _unselectedForegroundColor) .animate(_animationController); _animationController.value = 1.0; } @override void dispose() { if (_controller != null) _controller.dispose(); _scrollController.dispose(); super.dispose(); } Widget _buildButton(int index, Tab tab) { final TextStyle textStyle = (index == _currentIndex ? TextStyle.lerp( _unselectedLabelStyle, _labelStyle, _animationController.value) : (index == _prevIndex ? TextStyle.lerp( _labelStyle, _unselectedLabelStyle, _animationController.value) : _unselectedLabelStyle)); return Container( key: _tabKeys[index], // padding for the buttons margin: _buttonMargin, child: FlatButton( padding: _contentPadding, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, // get the color of the button's background (dependent of its state) color: index == _currentIndex ? _colorTweenBackgroundActivate.value : (index == _prevIndex ? _colorTweenBackgroundDeactivate.value : widget.unselectedBackgroundColor), // make the button a rectangle with round corners shape: RoundedRectangleBorder( borderRadius: new BorderRadius.circular(widget.radius)), onPressed: () { _goToIndex(index); }, child: Row( children: <Widget>[ IconTheme.merge( data: IconThemeData( size: 24.0, color: index == _currentIndex ? _colorTweenForegroundActivate.value : (index == _prevIndex ? _colorTweenForegroundDeactivate.value : _unselectedForegroundColor)), child: tab.icon), SizedBox( width: tab.icon != null && tab.text != null ? widget.labelSpacing : 0 ), tab.text != null ? Text( tab.text, style: textStyle, ) : Container() ] ) ) ); } @override Widget build(BuildContext context) { if (_controller == null) { _controller = widget.controller ?? DefaultTabController.of(context); // this will execute the function every time there's a swipe animation _controller.animation.addListener(_handleTabAnimation); } return AnimatedBuilder( animation: _colorTweenBackgroundActivate, builder: (context, child) => SizedBox( key: _tabsContainerKey, height: _kTabHeight, child: ListView.builder( physics: _scrollPhysics, controller: _scrollController, scrollDirection: Axis.horizontal, itemCount: widget.tabs.length, itemBuilder: (BuildContext context, int index) => _buildButton(index, widget.tabs[index])) ) ); } _handleTabAnimation() { _aniIndex = ((_controller.animation.value > _prevAniValue) ? _controller.animation.value : _prevAniValue) .round(); if (!_controller.indexIsChanging && _aniIndex != _currentIndex) { setState(() { _setCurrentIndex(_aniIndex); }); } _prevAniValue = _controller.animation.value; } _goToIndex(int index) { if (index != _currentIndex) { _setCurrentIndex(index); _controller.animateTo(index); } } _setCurrentIndex(int index) { setState(() { // change the index _prevIndex = _currentIndex; _currentIndex = index; _scrollTo(index); // scroll TabBar if needed }); _triggerAnimation(); } _triggerAnimation() { // reset the animation so it's ready to go _animationController.reset(); // run the animation! _animationController.forward(); } _scrollTo(int index) { // get the screen width. This is used to check if we have an element off screen RenderBox tabsContainer = _tabsContainerKey.currentContext.findRenderObject(); double screenWidth = tabsContainer.size.width; // get the button we want to scroll to RenderBox renderBox = _tabKeys[index].currentContext.findRenderObject(); // get its size double size = renderBox.size.width; // and position double position = renderBox.localToGlobal(Offset.zero).dx; // this is how much the button is away from the center of the screen and how much we must scroll to get it into place double offset = (position + size / 2) - screenWidth / 2; // if the button is to the left of the middle if (offset < 0) { // get the first button renderBox = _tabKeys[0].currentContext.findRenderObject(); // get the position of the first button of the TabBar position = renderBox.localToGlobal(Offset.zero).dx; // if the offset pulls the first button away from the left side, we limit that movement so the first button is stuck to the left side if (position > offset) offset = position; } else { // if the button is to the right of the middle // get the last button renderBox = _tabKeys.last.currentContext.findRenderObject(); // get its position position = renderBox.localToGlobal(Offset.zero).dx; // and size size = renderBox.size.width; // if the last button doesn't reach the right side, use it's right side as the limit of the screen for the TabBar if (position + size < screenWidth) screenWidth = position + size; // if the offset pulls the last button away from the right side limit, we reduce that movement so the last button is stuck to the right side limit if (position + size - offset < screenWidth) { offset = position + size - screenWidth; } } // scroll the calculated ammount _scrollController.animateTo(offset + _scrollController.offset, duration: new Duration(milliseconds: widget.duration), curve: Curves.easeInOut); } }
main.dart
import 'package:flutter/material.dart'; import 'buttons_tabbar.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Example(), ); } } class Example extends StatefulWidget { Example({Key key}) : super(key: key); @override _ExampleState createState() => _ExampleState(); } class _ExampleState extends State<Example> { @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: DefaultTabController( length: 6, child: Column(children: <Widget>[ ButtonsTabBar( backgroundColor: Colors.red, unselectedBackgroundColor: Colors.grey[300], unselectedLabelStyle: TextStyle(color: Colors.black), labelStyle: TextStyle( color: Colors.white, fontWeight: FontWeight.bold), tabs: [ Tab(icon: Icon(Icons.directions_car), text: "car"), Tab( icon: Icon(Icons.directions_transit), text: "transit", ), Tab(icon: Icon(Icons.directions_bike)), Tab(icon: Icon(Icons.directions_car)), Tab(icon: Icon(Icons.directions_transit)), Tab(icon: Icon(Icons.directions_bike)) ]), Expanded( child: TabBarView(children: <Widget>[ Center(child: Icon(Icons.directions_car)), Center(child: Icon(Icons.directions_transit)), Center(child: Icon(Icons.directions_bike)), Center(child: Icon(Icons.directions_car)), Center(child: Icon(Icons.directions_transit)), Center(child: Icon(Icons.directions_bike)) ])) ])))); } }
The flutter tutorial is a website that bring you the latest and amazing resources of code. All the languages codes are included in this website. The languages like flutter, android, java,kotlin etc.with the help of this languages any user can develop the beautiful application
For more information about Flutter. visit www.fluttertutorial.in