How to get current tab index in Flutter

In flutter implementing a tab layout is easy and straightforward. This is a simple example from the official documentation:

import 'package:flutter/material.dart'; void main() { runApp(new TabBarDemo()); } class TabBarDemo extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( home: new DefaultTabController( length: 3, child: new Scaffold( appBar: new AppBar( bottom: new TabBar( tabs: [ new Tab(icon: new Icon(Icons.directions_car)), new Tab(icon: new Icon(Icons.directions_transit)), new Tab(icon: new Icon(Icons.directions_bike)), ], ), title: new Text('Tabs Demo'), ), body: new TabBarView( children: [ new Icon(Icons.directions_car), new Icon(Icons.directions_transit), new Icon(Icons.directions_bike), ], ), ), ), ); } } 

But here is the thing, I want to get the active tab index so I can apply some logic on certain tabs. I search the documentation but I wasn't able to figure it out. Can you guys help and thanks?

1

9 Answers

The whole point of DefaultTabController is for it to manage tabs by itself.

If you want some custom tab management, use TabController instead. With TabController you have access to much more informations, including the current index.

class MyTabbedPage extends StatefulWidget { const MyTabbedPage({Key key}) : super(key: key); @override _MyTabbedPageState createState() => new _MyTabbedPageState(); } class _MyTabbedPageState extends State<MyTabbedPage> with SingleTickerProviderStateMixin { final List<Tab> myTabs = <Tab>[ new Tab(text: 'LEFT'), new Tab(text: 'RIGHT'), ]; TabController _tabController; @override void initState() { super.initState(); _tabController = new TabController(vsync: this, length: myTabs.length); } @override void dispose() { _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( bottom: new TabBar( controller: _tabController, tabs: myTabs, ), ), body: new TabBarView( controller: _tabController, children: myTabs.map((Tab tab) { return new Center(child: new Text(tab.text)); }).toList(), ), ); } } 
5

In this case, using StatefulWidget and State isn't a good idea.

You can get current index by DefaultTabController.of(context).index;.

Follow the code:

... appBar: AppBar( bottom: TabBar( tabs: [ Tab(~), Tab(~) ] ), actions: [ // At here you have to get `context` from Builder. // If you are not sure about this, check InheritedWidget document. Builder(builder: (context){ final index = DefaultTabController.of(context).index; // use index at here... }) ] ) 
3

You can access the current index when the tab is selected by onTap event of TabBar.

TabBar( onTap: (index) { //your currently selected index }, tabs: [ Tab1(), Tab2(), ]); 
1

Just apply a listener on the TabController.

// within your initState() method _tabController.addListener(_setActiveTabIndex); void _setActiveTabIndex() { _activeTabIndex = _tabController.index; } 

Use DefaultTabController you can get current index easily whether the user changes tabs by swiping or tap on the tab bar.

Important: You must wrap your Scaffold inside of a Builder and you can then retrieve the tab index with DefaultTabController.of(context).index inside Scaffold.

Example:

DefaultTabController( length: 3, child: Builder(builder: (BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Home'), bottom: TabBar( isScrollable: true, tabs: [Text('0'), Text('1'), Text('2')]), ), body: _buildBody(), floatingActionButton: FloatingActionButton( onPressed: () { print( 'Current Index: ${DefaultTabController.of(context).index}'); }, ), ); }), ), 

New working solution

I'd suggest you to use TabController for more customisations. To get active tab index you should use _tabController.addListener and _tabController.indexIsChanging.

Use this full code snippet:

 class CustomTabs extends StatefulWidget { final Function onItemPressed; CustomTabs({ Key key, this.onItemPressed, }) : super(key: key); @override _CustomTabsState createState() => _CustomTabsState(); } class _CustomTabsState extends State<CustomTabs> with SingleTickerProviderStateMixin { final List<Tab> myTabs = <Tab>[ Tab(text: 'LEFT'), Tab(text: 'RIGHT'), ]; TabController _tabController; int _activeIndex = 0; @override void initState() { super.initState(); _tabController = TabController( vsync: this, length: myTabs.length, ); } @override void dispose() { super.dispose(); _tabController.dispose(); } @override Widget build(BuildContext context) { double width = MediaQuery.of(context).size.width; _tabController.addListener(() { if (_tabController.indexIsChanging) { setState(() { _activeIndex = _tabController.index; }); } }); return Container( color: Colors.white, child: TabBar( controller: _tabController, isScrollable: true, indicatorPadding: EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0), indicator: BoxDecoration( borderRadius: BorderRadius.circular(10.0), color: Colors.green), tabs: myTabs .map<Widget>((myTab) => Tab( child: Container( width: width / 3 - 10, // - 10 is used to make compensate horizontal padding decoration: BoxDecoration( borderRadius: BorderRadius.circular(10.0), color: _activeIndex == myTabs.indexOf(myTab) ? Colors.transparent : Color(0xffA4BDD4), ), margin: EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0), child: Align( alignment: Alignment.center, child: Text( myTab.text, style: TextStyle(color: Colors.white), ), ), ), )) .toList(), onTap: widget.onItemPressed, ), ); } } 
1

Thanks to the example of Rémi Rousselet, you can do it, the code like this:

_tabController.index 

This will return the current index of the position of your TabBarView

0

You can add a listener to listen to changes in tabs like below

tabController = TabController(vsync: this, length: 4) ..addListener(() { setState(() { switch(tabController.index) { case 0: // some code here case 1: // some code here } }); }); 
1

This Code will give you index of Active tab , also save the tab index for future use, and when you back to the tab page the the previous active page will be displayed.

import 'package:flutter/material.dart'; void main() { runApp(new TabBarDemo()); } class TabBarDemo extends StatelessWidget { TabScope _tabScope = TabScope.getInstance(); @override Widget build(BuildContext context) { return new MaterialApp( home: new DefaultTabController( length: 3, index: _tabScope.tabIndex, // child: new Scaffold( appBar: new AppBar( bottom: new TabBar( onTap: (index) => _tabScope.setTabIndex(index), //current tab index tabs: [ new Tab(icon: new Icon(Icons.directions_car)), new Tab(icon: new Icon(Icons.directions_transit)), new Tab(icon: new Icon(Icons.directions_bike)), ], ), title: new Text('Tabs Demo'), ), body: new TabBarView( children: [ new Icon(Icons.directions_car), new Icon(Icons.directions_transit), new Icon(Icons.directions_bike), ], ), ), ), ); } } class TabScope{ // singleton class static TabScope _tabScope; int tabIndex = 0; static TabScope getInstance(){ if(_tabScope == null) _tabScope = TabScope(); return _tabScope; } void setTabIndex(int index){ tabIndex = index; } } 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like