如何在Flutter中获取当前选项卡索引

Ton*_*Joe 7 tabcontrol flutter flutter-layout

在颤动中,实现标签布局既简单又直接.这是官方文档中的一个简单示例:

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),
            ],
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

但事情就是这样,我想获得活动的tab索引,以便我可以在某些选项卡上应用一些逻辑.我搜索文档,但我无法弄清楚.你们能帮帮忙吗?

Usm*_*man 22

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

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

    tabs: [
      Tab1(),
      Tab2(),
    ]);
Run Code Online (Sandbox Code Playgroud)

  • 如果用户通过滑动更改选项卡,则这不会按预期工作。仅当他们实际点击标签栏时。 (15认同)

Rém*_*let 19

整个问题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(),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 在此示例中,如何获取索引?我尝试添加列表器,但是在构建特定的选项卡视图之后,侦听器正在打印索引,我希望在构建特定选项卡的布局之前获取索引有什么想法? (6认同)
  • 要获取选项卡的索引,只需执行 `_tabController.index` (5认同)

Coa*_*alB 10

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

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

void _setActiveTabIndex() {
  _activeTabIndex = _tabController.index;
}
Run Code Online (Sandbox Code Playgroud)


小智 8

在这种情况下,使用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... 
    })
  ]
)

Run Code Online (Sandbox Code Playgroud)

  • 将整个“Scaffold”包裹在“Builder”中对我来说很有效。 (2认同)
  • 这应该被接受的答案。最简单的解决方案,需要最少的代码修改。 (2认同)

Doa*_*Bui 8

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

重要提示:您必须将Scaffold内部包裹在 a 中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}');
          },
        ),
      );
    }),
  ),
Run Code Online (Sandbox Code Playgroud)


Rus*_*809 7

新的工作解决方案

我建议您使用TabController更多自定义功能。要获取活动选项卡索引,您应该使用_tabController.addListener.

使用这个完整的代码片段


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,
    );
    _tabController.addListener(() {
      setState(() {
        _activeIndex = _tabController.index;
        print('_activeIndex: $_activeIndex');
      });
    });
  }

  @override
  void dispose() {
    super.dispose();
    _tabController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    double width = MediaQuery.of(context).size.width;
    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,
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*Pad 5

感谢 R\xc3\xa9mi Rousselet 的例子,可以做到,代码如下:

\n\n
_tabController.index\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n