Flutter CupertinoTabBar: невозможно переключиться на вкладку по индексу для события потока

Попытка активировать CupertinoTabBar's вкладка 0, в то время как вкладка 1 активна на stream event как это:

{

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, а это не то, что нам нужно.

С чем это связано, как мы можем перейти на вкладку внешнего события?

1 ответ

Это решается с помощью StreamBuilder, метод, который был на самом деле попытался первым. Этот метод имеет другое предостережение: он переключается на вкладку 0, когда нам нужно остаться, например, на 1-й вкладке, и это происходит, когда мы возвращаемся с другого экрана, открытого в верхней части экрана с вкладками.

Что не так в этот раз? Построитель потока перезапускает последнее событие (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();
                  }
                },
              );
            },
          ),
        );
      }
}

Вы также можете использовать GlobalKeys, и ваша проблема должна исчезнуть. Вот четкое руководство о том, как это сделать

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

Другие вопросы по тегам