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

DartFlutter

Dart Problem Overview


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

Dart Solutions


Solution 1 - Dart

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(...);

Solution 2 - Dart

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);

Solution 3 - Dart

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;
});

Solution 4 - Dart

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.

Solution 5 - Dart

If you want to jump to a specific page, you can use

PageController.jumpToPage(int)

However if you need animation, you'd use

PageController.animateToPage(page, duration: duration, curve: curve)

Simple example demonstrating it.

// create a PageController
final _controller = PageController();
bool _shouldAnimate = true; // whether we animate or jump

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(),
    floatingActionButton: FloatingActionButton(
      onPressed: () {
        if (_shouldAnimate) {
          // animates to page1 with animation
          _controller.animateToPage(1, duration: Duration(seconds: 1), curve: Curves.easeOut);  
        } else {
          // jump to page1 without animation
          _controller.jumpToPage(1);
        }
      },
    ),
    body: PageView(
      controller: _controller, // assign it to PageView
      children: <Widget>[
        FlutterLogo(colors: Colors.orange), // page0
        FlutterLogo(colors: Colors.green), // page1
        FlutterLogo(colors: Colors.red), // page2
      ],
    ),
  );
}

Solution 6 - Dart

DefaultTabController(
              length: 4,
              initialIndex: 0,
              child: TabBar(
                tabs: [
                  Tab(
                    child: Text(
                      "People",
                      style: TextStyle(
                        color: Colors.black,
                      ),
                    ),
                  ),
                  Tab(
                    child: Text(
                      "Events",
                      style: TextStyle(
                        color: Colors.black,
                      ),
                    ),
                  ),
                  Tab(
                    child: Text(
                      "Places",
                      style: TextStyle(
                        color: Colors.black,
                      ),
                    ),
                  ),
                  Tab(
                    child: Text(
                      "HashTags",
                      style: TextStyle(
                        color: Colors.black,
                      ),
                    ),
                  ),
                ],
              ),
            )

Solution 7 - Dart

class Tab bar

    class TabBarScreen extends StatefulWidget {
      TabBarScreen({Key key}) : super(key: key);
    
      @override
      _TabBarScreenState createState() => _TabBarScreenState();
    }
    
    final List<Tab> tabs = <Tab>[
      Tab(text: 'Page1'),
      Tab(text: 'Page2'),
    ];
    
    class _TabBarScreenState extends State<TabBarScreen> with SingleTickerProviderStateMixin {
    
      TabController tabController;
    
      @override
      void initState() {
        super.initState();
        tabController = new TabController(vsync: this, length: tabs.length);
      }
    
      @override
      void dispose() {
        tabController.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return DefaultTabController(
          length: 2,
          child: Scaffold(
            backgroundColor: Theme.of(context).primaryColor,
            appBar: AppBar(
              backgroundColor: Theme.of(context).primaryColor,
              centerTitle: true,
              shape: Border(bottom: BorderSide(color: Colors.white)),
              title: Text("Tab Bar",),
              bottom: TabBar(
                controller: tabController,
                tabs: tabs,
                indicatorWeight: 5,
                indicatorColor: Colors.white,
                labelColor: Colors.white,
              ),
            ),
            body: TabBarView(
              controller: tabController,
              children: [
                PageOneScreen(controller: tabController),
                PageTwoScreen(controller: tabController),
              ],
            ),
          ),
        );
      }
    }

class PageOne

    class PageOneScreen extends StatefulWidget {
    @override
    _PageOneScreenState createState() => _PageOneScreenState();

       PageOneScreen({controller}) {
          tabController = controller;
       }
    }

    TabController tabController;

    class _PageOneScreenState extends State<PageOneScreen> {
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            RaisedButton(
              onPressed: () {
                tabController.animateTo(1); // number : index page
              },
              child: Text(
                "Go To Page 2",
              ),
            ),
          ],
        );
      }
    }

Solution 8 - Dart

i was trying to solve similar issue but passing methods or controllers down the widget tree wasn't a clean option for me. i had requirement to go back to tabbed page from other non-tabbed routes (back to specific tabs). following solution worked for me

Inside tabbed page: read route arguments

@override
  Widget build(BuildContext context) {
     final String? tabId = Get.arguments;
       
    _selectedTabIndex = tabId !=null? int.parse(tabId): 0;

    return Scaffold(
    ....
     body: _pages[_selectedPageIndex]['page'] as Widget,
     bottomNavigationBar: BottomNavigationBar(
     onTap: _selectPage,
    ....);

}

Now the calling page

onSubmit:() { // or some other event
      // do something here

      Get.offAndToNamed(Routes.homeTabs,
          arguments: TabIndex.specialTab.index.toString());
      //Routes is a const & TabIndex is enum defined somewhere
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSunit GautamView Question on Stackoverflow
Solution 1 - DartchemamolinsView Answer on Stackoverflow
Solution 2 - DartGloatingCoderView Answer on Stackoverflow
Solution 3 - DartWaister NunesView Answer on Stackoverflow
Solution 4 - DartFPI.MDView Answer on Stackoverflow
Solution 5 - DartCopsOnRoadView Answer on Stackoverflow
Solution 6 - DartHanshirView Answer on Stackoverflow
Solution 7 - DartALNAJJARView Answer on Stackoverflow
Solution 8 - DartSaf RahmanView Answer on Stackoverflow