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