Flutter CupertinoTabBar:在流事件中无法按索引切换到选项卡

时间:2019-03-05 13:24:16

标签: flutter-cupertino cupertinotabbar

尝试在CupertinoTabBar's上激活标签1时激活stream event标签0,如下所示:

{

class HomeScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => HomeScreenState();
}

class HomeScreenState extends State<HomeScreen> {

  int _currentTabIndex = 0;

  @override
  void initState() {
    super.initState();
    _drawerStream.listen((state) {
      if (_currentTabIndex != 0) {
        SchedulerBinding.instance.addPostFrameCallback((_) {
          setState(() => _currentTabIndex = 0);
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: Drawer(
        elevation: 0.0,
        child: DrawerScreen(),
      ),
      body: CupertinoTabScaffold(
        tabBar: CupertinoTabBar(
          onTap: (index) {
            _currentTabIndex = index;
          },
          currentIndex: _currentTabIndex,
          backgroundColor: Colors.white,
          items: <BottomNavigationBarItem>[
            BottomNavigationBarItem(
              title: Text('Main'),
              icon: Icon(IconData(0xe800), size: 20),
            ),
            BottomNavigationBarItem(
              title: Text('Goodies'),
              icon: Icon(IconData(0xe84b), size: 20),
            ),
          ],
        ),
        tabBuilder: (BuildContext context, int index) {
          return CupertinoTabView(
            builder: (BuildContext context) {
              switch (index) {
                case 0: return MainScreen();
                case 1: return GoodiesScreen();
              }
            },
          );
        },
      ),
    );
  }
}
}

当事件来自_drawerStream时,视觉上什么也没有发生。仍在跟踪调试器的运行情况,发现CupertinoTabBar小部件生成了2次,第一次生成了当前索引参数0,这是我们实际需要的。但是在第二次运行时,它将使用当前索引参数设置为1进行重建,这不是我们想要的。

原因是什么,我们如何在外部事件上切换到选项卡?

2 个答案:

答案 0 :(得分:1)

使用StreamBuilder解决了该问题,该方法实际上是最先尝试的。此方法有一个不同的警告:当我们必须停留在第一个选项卡时,它将切换到选项卡0,而当我们从在带有选项卡的屏幕顶部打开的另一个屏幕返回时,会发生这种情况。

这次是怎么了?流构建器重新发出上一个事件(基于BehaviourSubject的流),并将_currentTabIndex设置为0,而我们需要它来保持当前值。解决方案是“记住”最后一个事件并识别它刚刚被重新发射。这可能无法解决所有类似问题,但至少可以提供一个线索。

一段代码来说明解决方案:

class HomeScreenState extends State<HomeScreen> {

  int _currentTabIndex = 0;
  AsyncSnapshot<UIState> lastSnapshot;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: Drawer(
        elevation: 0.0,
        child: DrawerScreen(),
      ),
      body: StreamBuilder(
        stream: _drawerStream,
        builder: (context, AsyncSnapshot<UIState> snapshot) {
          if (_currentTabIndex != 0 && lastSnapshot != snapshot) {
            SchedulerBinding.instance.addPostFrameCallback((_) =>
              setState(() => _currentTabIndex = nextTab));
          }
          lastSnapshot = snapshot;
          return CupertinoTabScaffold(
            tabBar: CupertinoTabBar(
              onTap: (index) {
                _currentTabIndex = index;
              },
              currentIndex: _currentTabIndex,
              backgroundColor: Colors.white,
              items: <BottomNavigationBarItem>[
                BottomNavigationBarItem(
                  title: Text('Main'),
                  icon: Icon(IconData(0xe800), size: 20),
                ),
                BottomNavigationBarItem(
                  title: Text('Goodies'),
                  icon: Icon(IconData(0xe84b), size: 20),
                ),
              ],
            ),
            tabBuilder: (BuildContext context, int index) {
              return CupertinoTabView(
                builder: (BuildContext context) {
                  switch (index) {
                    case 0: return MainScreen();
                    case 1: return GoodiesScreen();
                  }
                },
              );
            },
          ),
        );
      }
}

答案 1 :(得分:0)

您还可以使用GlobalKeys,您的问题应该会消失。这是有关操作方法的清晰教程

https://medium.com/@info_4766/ios-tab-bar-in-flutter-9379cf09df31