Drawer
每次用户按下 中的按钮时,我都想关闭我的小部件Bottom Navigation Bar
,但无法完全弄清楚这件事。我现在设置 BNB 的方式是通过应用程序记住所有屏幕的当前状态(使用IndexedStack
),但是如果在按下 BNB 按钮之前在任何屏幕中打开抽屉,我想关闭抽屉. 我的每个屏幕都有自己的抽屉和 AppBars,所以我不能在 BNB 内制作一个抽屉(或者我可以并且我可以在点击特定屏幕时使用开关盒动态更改它们,但是抽屉将覆盖底部导航栏等),但我现在想让它像这样工作。所以这是代码,里面有一些注释来解释事情:
底部导航栏:
class BottomNavBar extends StatefulWidget {
static const String id = 'bottom_navbar_screen';
@override
_BottomNavBarState createState() => _BottomNavBarState();
}
class _BottomNavBarState extends State<BottomNavBar> {
int _selectedIndex = 0;
/// list of screen that will render inside the BNB
List<Navigation> _items = [
Navigation(
widget: Screen1(), navigationKey: GlobalKey<NavigatorState>()),
Navigation(
widget: Screen2(), navigationKey: GlobalKey<NavigatorState>()),
Navigation(
widget: Screen3(), navigationKey: GlobalKey<NavigatorState>()),
Navigation(
widget: Screen4(), navigationKey: GlobalKey<NavigatorState>()),
];
/// function that renders components based on selected one in the BNB
void _onItemTapped(int index) {
if (index == _selectedIndex) {
_items[index]
.navigationKey
.currentState
.popUntil((route) => route.isFirst);
} else {
setState(() {
_selectedIndex = index;
});
}
/// when the index is selected, on the button press do some actions
switch (_selectedIndex) {
case 0:
// Do some actions
break;
case 1:
// Do some actions
break;
case 2:
// Do some actions
break;
case 3:
// Do some actions
break;
}
}
/// navigation Tab widget for a list of all the screens and puts them in a Indexed Stack
Widget _navigationTab(
{GlobalKey<NavigatorState> navigationKey, Widget widget}) {
return Navigator(
key: navigationKey,
onGenerateRoute: (routeSettings) {
return MaterialPageRoute(builder: (context) => widget);
},
);
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
final isFirstRouteInCurrentTab =
!await _items[_selectedIndex].navigationKey.currentState.maybePop();
if (isFirstRouteInCurrentTab) {
if (_selectedIndex != 0) {
_onItemTapped(1);
return false;
}
}
/// let system handle back button if we're on the first route
return isFirstRouteInCurrentTab;
},
child: Scaffold(
body: IndexedStack(
index: _selectedIndex,
children: _items
.map((e) => _navigationTab(
navigationKey: e.navigationKey, widget: e.widget))
.toList(),
),
bottomNavigationBar: BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
label: 'Screen 1,
),
BottomNavigationBarItem(
label: 'Screen 2,
),
BottomNavigationBarItem(
label: 'Screen 3,
),
BottomNavigationBarItem(
label: 'Screen 4,
),
],
currentIndex: _selectedIndex,
showUnselectedLabels: true,
onTap: _onItemTapped,
),
),
);
}
}
假设所有 4 个屏幕都是相同的,并且它们有自己的 AppBar 和 Drawer:
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
drawer: Drawer(), // so this is what I want to close on BNB button press in each of the 4 screens
appBar: AppBar( // each screen has its own app bar
title: Text('Screens 1-4'),
),
body: Text('Body of Screens 1-4'),
);
}
所以因为每个屏幕都有自己的 AppBars 和 Drawer,所以 Drawer 不会渲染在底部导航栏上,所以我的 BNB 按钮可以点击。如果我在 BNB 内为所有屏幕放置一个抽屉,那么除非你先关闭抽屉,否则你无法单击 BNB,这不是我现在要寻找的东西。
所以,我的最后一个问题是,当您按下底部导航栏时,如何关闭每个屏幕抽屉(如果它们以前打开过)?(即我在屏幕 1 上,打开抽屉,然后按 BNB 中的屏幕 2,我想pop()
/关闭屏幕 1 中的抽屉,然后导航到屏幕 2。)
在此先感谢您的帮助!