如何以编程方式在Flutter中选择BottomNavigationBar标签,而不是内置的onTap回调?

时间:2018-06-21 05:46:07

标签: dart flutter bottomnavigationview material-components

我一直在使用BottomNavigationBar,但无法在BottomNavigationBar的onTap回调之外以编程方式选择Tab。

下面的代码带有onTap回调[正在运行]

    return new BottomNavigationBar(
  items: <BottomNavigationBarItem>[
    _bottomNavigationItem(Icons.account_circle, DrawerTitles.CONTACTS),
    _bottomNavigationItem(Icons.delete, DrawerTitles.DELETED_CONTACTS),
    _bottomNavigationItem(Icons.list, DrawerTitles.LOGS),
  ],
  onTap: (int index) {
    setState(() {
      navigationIndex = index;
      switch (navigationIndex) {
        case 0:
          handleBottomNavigationBarClicks(DrawerTitles.CONTACTS);
          break;
        case 1:
          handleBottomNavigationBarClicks(DrawerTitles.DELETED_CONTACTS);
          break;
        case 2:
          handleBottomNavigationBarClicks(DrawerTitles.LOGS);
          break;
      }
    });
  },
  currentIndex: navigationIndex,
  fixedColor: Colors.blue[400],
  type: BottomNavigationBarType.fixed,
);

但是我想在onTap回调之外更改选项卡吗?

我曾尝试在onTap回调之外更改BottomNavigatioBar所使用的索引,但这没有用。

这是我尝试过的-

void changeTabs(int tabIndex) {
setState(() {
     navigationIndex = tabIndex;
});}

有什么办法可以更改标签页?

这是代码的要旨

https://gist.github.com/harsh159357/62f338a196b0e5edad7aed5017dae3e5

4 个答案:

答案 0 :(得分:5)

您可以使用GlobalKey来获取此BottomAppBar小部件。通过此GlobalKey,您可以处理此小部件。 Here is an gist for the code

在这里分配一个GlobalKey

GlobalKey globalKey = new GlobalKey(debugLabel: 'btm_app_bar');

并将该键放入您的BottomNavigationBar

new BottomNavigationBar(
    key: globalKey,
    items: [...],
   onTap: (int index) {...},
  ),

现在您可以调用小部件的方法

 final BottomNavigationBar navigationBar = globalKey.currentWidget;
 navigationBar.onTap(2);

答案 1 :(得分:4)

这里是有关如何实现所需目标的完整示例。

import 'package:flutter/material.dart';

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

const String page1 = "Page 1";
const String page2 = "Page 2";
const String page3 = "Page 3";
const String title = "BNB Demo";

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

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Widget> _pages;
  Widget _page1;
  Widget _page2;
  Widget _page3;

  int _currentIndex;
  Widget _currentPage;

  @override
  void initState() {
    super.initState();

    _page1 = Page1();
    _page2 = Page2();
    _page3 = Page3();

    _pages = [_page1, _page2, _page3];

    _currentIndex = 0;
    _currentPage = _page1;
  }

  void changeTab(int index) {
    setState(() {
      _currentIndex = index;
      _currentPage = _pages[index];
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: _currentPage,
      bottomNavigationBar: BottomNavigationBar(
          onTap: (index) => changeTab(index),
          currentIndex: _currentIndex,
          items: [
            BottomNavigationBarItem(
                title: Text(page1), icon: Icon(Icons.account_circle)),
            BottomNavigationBarItem(
                title: Text(page2), icon: Icon(Icons.account_circle)),
            BottomNavigationBarItem(
                title: Text(page3), icon: Icon(Icons.account_circle))
          ]),
      drawer: new Drawer(
        child: new Container(
          margin: EdgeInsets.only(top: 20.0),
          child: new Column(
            children: <Widget>[
              navigationItemListTitle(page1, 0),
              navigationItemListTitle(page2, 1),
              navigationItemListTitle(page3, 2),
            ],
          ),
        ),
      ),
    );
  }

  Widget navigationItemListTitle(String title, int index) {
    return new ListTile(
      title: new Text(
        title,
        style: new TextStyle(color: Colors.blue[400], fontSize: 22.0),
      ),
      onTap: () {
        Navigator.pop(context);
        changeTab(index);
      },
    );
  }
}

class Page1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(page1),
    );
  }
}

class Page2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(page2),
    );
  }
}

class Page3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(page3),
    );
  }
}

要更改为标签页时,请致电changeTab(YOUR_TAB_INDEX)

答案 2 :(得分:0)

感谢@HuyHoàng 提供 flutter version 2+ 我使用这个:

var key=new GlobalKey<State<BottomNavigationBar>>();

然后将此键分配给 BottomNavigationBar 然后可以访问底部,如下所示:

BottomNavigationBar navigationBar =  bottomWidgetKey.currentWidget as BottomNavigationBar;
navigationBar.onTap!(1);

答案 3 :(得分:-1)

CupertinoApp 的另一种解决方案。它适用于我的应用要求。

这也是“有什么办法可以改变孩子的标签吗?”的答案,因为我们可以在任何孩子中传递控制器,我们可以改变标签索引。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(CupertinoApp(home: HomeScreen(),));
}

final GlobalKey<NavigatorState> firstTabNavKey = GlobalKey<NavigatorState>();
final GlobalKey<NavigatorState> secondTabNavKey = GlobalKey<NavigatorState>();
final GlobalKey<NavigatorState> thirdTabNavKey = GlobalKey<NavigatorState>();

class HomeScreen extends StatelessWidget {

  var controller = CupertinoTabController(initialIndex: 0);

  @override
  Widget build(BuildContext context) {
    return CupertinoTabScaffold(
        controller: controller,
        tabBar: CupertinoTabBar(
          items: <BottomNavigationBarItem>[
            BottomNavigationBarItem(icon: Icon(CupertinoIcons.home)),
            BottomNavigationBarItem(icon: Icon(CupertinoIcons.cart)),
            BottomNavigationBarItem(icon: Icon(CupertinoIcons.person)),
          ],
        ),
        tabBuilder: (context, index) {
          if (index == 0) {
            return CupertinoTabView(navigatorKey: firstTabNavKey, builder: (context) => FirstTab(controller: this.controller,),);
          } else if (index == 1) {
            return CupertinoTabView(navigatorKey: secondTabNavKey, builder: (context) => SecondTab(),);
          } else {
            return CupertinoTabView(navigatorKey: thirdTabNavKey, builder: (context) => ThirdTab(),);
          }
        }
    );
  }
}

class FirstTab extends StatelessWidget {
  final CupertinoTabController controller;

  FirstTab({required this.controller});

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold( child: Container(
      child: Center(
        child: Row(
          children: <Widget>[
            TextButton(onPressed: () => {controller.index = 1}, child: Text('Second Tab')),
            TextButton(onPressed: () => {controller.index = 2}, child: Text('Third Tab')),
          ],
        ),
      ),
    ));
  }
}

class SecondTab extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold( child:Container(child: Center( child: Text('Second Screen'),),));
  }
}

class ThirdTab extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold( child:Container(child: Center( child: Text('Third Screen'),),));
  }
}