Flutter: Changing the current tab in tab bar view using a button

I am creating an app that contains a tab bar on its homepage. I want to be able to navigate to one of the tabs using my FloatingActionButton. In addition, I want to keep the default methods of navigating to that tab, i.e. by swiping on screen or by clicking the tab.

I also want to know how to link that tab to some other button.

Here is a screenshot of my homepage.

Homepage with navigation tabs and floating action button


You need to get the TabBar controller and call its animateTo() method from the button onPressed() handle.

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyTabbedPage(),
    );
  }
}

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(
        title: new Text("Tab demo"),
        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(),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () => _tabController.animateTo((_tabController.index + 1) % 2), // Switch tabs
        child: new Icon(Icons.swap_horiz),
      ),
    );
  }
}

If you use a GlobalKey for the MyTabbedPageState you can get the controller from any place, so you can call the animateTo() from any button.

class MyApp extends StatelessWidget {
  static final _myTabbedPageKey = new GlobalKey<_MyTabbedPageState>();

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyTabbedPage(
        key: _myTabbedPageKey,
      ),
    );
  }
}

You could call it from anywhere doing:

MyApp._myTabbedPageKey.currentState._tabController.animateTo(...);


I am super late, but hopefully someone benefits from this. just add this line to your onPressed of your button and make sure to change the index number to your preferred index:

DefaultTabController.of(context).animateTo(1);

You can use TabController:

TabController _controller = TabController(
  vsync: this,
  length: 3,
  initialIndex: 0,
);

_controller.animateTo(_currentTabIndex);

return Scaffold(
  appBar: AppBar(
    bottom: TabBar(
      controller: _controller,
      tabs: [
        ...
      ],
    ),
  ),
  body: TabBarView(
    controller: _controller,
    children: [
      ...
    ],
  ),
);

And than, setState to update screen:

int _currentTabIndex = 0;

setState(() {
  _currentTabIndex = 1;
});

chemamolin's answer above is correct, but for additional clarification/tip, if you want to call your tabcontroller "from anywhere", also make sure the tabcontroller is not a private property of the class by removing the underscore, otherwise the distant class will not be able to see the tabcontroller with the example provided even when using the GlobalKey.

In other words, change

TabController _tabController;

to:

TabController tabController;

and change

MyApp._myTabbedPageKey.currentState._tabController.animateTo(...);

to:

MyApp._myTabbedPageKey.currentState.tabController.animateTo(...);

and everywhere else you reference tabcontroller.