Flutter使用persistent_bottom_nav_bar时如何通过底部导航项触发drawer
实现方案
方案1:拦截底部导航点击事件直接打开Drawer(推荐)
这是最直接的实现方式,不需要跳转页面,实现逻辑如下:
- 定义全局
ScaffoldKey用来控制Drawer的打开和关闭 - 在
PersistentTabView中添加onItemSelected回调,拦截最后一项(索引为3)的点击事件,阻止默认的tab切换行为,直接调用方法打开Drawer - 给外层Scaffold配置
drawer/endDrawer属性,传入你需要的侧边栏内容
修改后的代码示例:
class BottomNav extends StatefulWidget { const BottomNav({Key? key}) : super(key: key); @override _BottomNavState createState() => _BottomNavState(); } class _BottomNavState extends State<BottomNav> { late PersistentTabController _controller; // 新增scaffoldKey用于控制侧边栏 final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); @override void initState() { super.initState(); _controller = PersistentTabController(initialIndex: 0); } List<Widget> _buildScreens() { return [ HomePage(), HistoryPage(), ServicePage(), // 第四个页面不会实际跳转,留空即可 const SizedBox.shrink(), ]; } List<PersistentBottomNavBarItem> _navBarsItems() { return [ PersistentBottomNavBarItem( icon: Icon(Icons.home), title: ("Home"), textStyle: TextStyle(fontWeight: FontWeight.w700, fontSize: 10), activeColorPrimary: themeBlue, inactiveColorPrimary: greyColor, ), PersistentBottomNavBarItem( icon: Icon(Icons.history), title: ("History"), activeColorPrimary: themeBlue, textStyle: TextStyle(fontWeight: FontWeight.w700, fontSize: 10), inactiveColorPrimary: greyColor, ), PersistentBottomNavBarItem( icon: Icon(Icons.apps_outlined), title: ("Services"), activeColorPrimary: themeBlue, textStyle: TextStyle(fontWeight: FontWeight.w700, fontSize: 10), inactiveColorPrimary: greyColor, ), PersistentBottomNavBarItem( icon: Icon(CupertinoIcons.person_alt_circle), title: ("Profile"), activeColorPrimary: themeBlue, inactiveColorPrimary: greyColor, textStyle: TextStyle(fontWeight: FontWeight.w700, fontSize: 10), ), ]; } @override Widget build(BuildContext context) { return Scaffold( key: _scaffoldKey, // 配置侧边栏内容,可替换为你自定义的Drawer组件 drawer: Drawer( child: ListView( padding: EdgeInsets.zero, children: const [ DrawerHeader( decoration: BoxDecoration(color: Colors.blue), child: Text('侧边栏标题'), ), ListTile(title: Text('菜单选项1')), ListTile(title: Text('菜单选项2')), ], ), ), body: PersistentTabView( context, controller: _controller, screens: _buildScreens(), items: _navBarsItems(), // 新增点击事件拦截逻辑 onItemSelected: (index) { if (index == 3) { // 点击最后一项时打开侧边栏 _scaffoldKey.currentState?.openDrawer(); // 返回false阻止tab切换 return false; } // 其他选项正常切换tab return true; }, confineInSafeArea: true, backgroundColor: Colors.white, handleAndroidBackButtonPress: true, popAllScreensOnTapOfSelectedTab: true, popActionScreens: PopActionScreensType.all, itemAnimationProperties: ItemAnimationProperties( duration: Duration(milliseconds: 200), curve: Curves.ease, ), screenTransitionAnimation: ScreenTransitionAnimation( animateTabTransition: true, curve: Curves.ease, duration: Duration(milliseconds: 200), ), navBarStyle: NavBarStyle.style6, ), ); } }
方案2:兜底兼容方案
如果你使用的persistent_bottom_nav_bar版本不支持onItemSelected返回bool拦截切换逻辑,可以用该方案:
- 把第四个页面改为全透明页面,在页面初始化时触发打开Drawer
- 监听Drawer的关闭事件,关闭后自动切回之前的tab索引即可
内容的提问来源于stack exchange,提问作者user14824032
相关产品推荐
相关产品推荐

