41

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?

4

9 回答 9

53

的全部意义DefaultTabController在于它自己管理标签。

如果您想要一些自定义选项卡管理,请TabController改用。TabController您可以访问更多信息,包括当前索引。

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(),
      ),
    );
  }
}
于 2018-05-01T20:52:04.173 回答
49

在这种情况下,使用StatefulWidgetandState不是一个好主意。

您可以通过 获取当前索引DefaultTabController.of(context).index;

按照代码:

...
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... 
    })
  ]
)

于 2019-02-09T13:58:23.997 回答
25

通过 TabBar 的 onTap 事件选择选项卡时,您可以访问当前索引。

TabBar(
    onTap: (index) {
      //your currently selected index
    },

    tabs: [
      Tab1(),
      Tab2(),
    ]);
于 2019-07-10T10:15:15.613 回答
14

只需在 TabController 上应用一个侦听器。

// within your initState() method
_tabController.addListener(_setActiveTabIndex);

void _setActiveTabIndex() {
  _activeTabIndex = _tabController.index;
}
于 2019-07-12T22:43:22.670 回答
8

使用DefaultTabController您可以轻松获取当前索引,无论用户是通过滑动还是点击标签栏来更改标签。

重要提示:您必须将您的Scaffoldinside 包裹起来,Builder然后您可以使用DefaultTabController.of(context).indexinside检索选项卡索引Scaffold

例子:

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}');
          },
        ),
      );
    }),
  ),
于 2020-06-30T10:36:07.683 回答
3

感谢Rémi Rousselet的例子,你可以做到,代码如下:

_tabController.index

这将返回您的 TabBarView 位置的当前索引

于 2019-06-27T09:43:01.317 回答
2

新的工作解决方案

我建议你使用TabController更多的定制。要获得活动标签索引,您应该使用_tabController.addListenerand _tabController.indexIsChanging

使用这个完整的代码片段


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,
      ),
    );
  }
}
于 2021-04-03T09:03:58.937 回答
2

您可以添加一个侦听器来侦听选项卡中的更改,如下所示

tabController = TabController(vsync: this, length: 4)
   ..addListener(() {
setState(() {
  switch(tabController.index) {
    case 0:
      // some code here
    case 1:
     // some code here
  }
  });
});
于 2020-05-16T21:48:08.600 回答
-2

此代码将为您提供活动选项卡的索引,同时保存选项卡索引以供将来使用,当您返回选项卡页面时,将显示上一个活动页面。

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;
      }
    }
于 2020-04-25T17:03:34.043 回答