【问题标题】:How to get current tab index in Flutter如何在 Flutter 中获取当前选项卡索引
【发布时间】:2021-04-03 17:25:15
【问题描述】:

在 Flutter 中实现选项卡布局简单明了。这是来自官方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),
            ],
          ),
        ),
      ),
    );
  }
}

但事情是这样的,我想获取活动标签索引,以便我可以在某些标签上应用一些逻辑。我搜索了文档,但我无法弄清楚。可以帮忙看看吗?

【问题讨论】:

标签: flutter tabcontrol flutter-layout


【解决方案1】:

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

【讨论】:

  • 在这个例子中如何获取索引??我尝试添加列表器,但在构建特定选项卡视图之后,监听器正在打印我想要在构建特定选项卡布局之前获取索引的索引有什么想法吗?
  • 只有状态?
  • 嘿@sarveshchavan 你有什么解决办法吗?
  • 要获取标签的索引,只需执行_tabController.index
  • 谢谢哥们,需要放置控制器:两个地方都为我工作!!
【解决方案2】:

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

您可以通过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... 
    })
  ]
)

【讨论】:

  • 将整个 Scaffold 包裹在 Builder 中对我有用。
  • 谢谢,这就是我一直在寻找的。 ???
  • 这应该是被接受的答案。最简单的解决方案,需要最少的代码修改。
【解决方案3】:

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

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

    tabs: [
      Tab1(),
      Tab2(),
    ]);

【讨论】:

  • 如果用户通过滑动来更改选项卡,这将无法正常工作。仅当他们实际点击标签栏时。
【解决方案4】:

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

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

void _setActiveTabIndex() {
  _activeTabIndex = _tabController.index;
}

【讨论】:

    【解决方案5】:

    使用DefaultTabController,无论用户通过滑动点击标签栏上的方式切换标签,您都可以轻松获取当前索引。

    重要提示:您必须将 Scaffold 包裹在 Builder 中,然后您可以在 Scaffold 中使用 DefaultTabController.of(context).index 检索选项卡索引。

    例子:

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

    【讨论】:

      【解决方案6】:

      新的工作解决方案

      我建议您使用TabController 进行更多自定义。要获得活动标签索引,您应该使用_tabController.addListener_tabController.indexIsChanging

      使用这个完整代码sn-p

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

      【讨论】:

      • 真正帮助了我而不是所有其他答案
      【解决方案7】:

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

      _tabController.index
      

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

      【讨论】:

        【解决方案8】:

        您可以添加一个监听器来监听如下选项卡中的变化

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

        【讨论】:

        • 在此之后不要忘记重新启动应用程序,而不仅仅是使用热重载。由于热重载不一定会再次为您的屏幕运行 initState。
        【解决方案9】:

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

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

        【讨论】:

          猜你喜欢
          • 2015-09-19
          • 2010-09-22
          • 1970-01-01
          • 1970-01-01
          • 2013-04-07
          • 1970-01-01
          • 2022-11-21
          • 1970-01-01
          • 2013-04-24
          相关资源
          最近更新 更多