Flutter点击底部导航栏项打开Bottom Sheet的实现问题
解决方案
现有代码的问题
- 你错误地将弹窗方法
showBottomSheet()放到了页面组件数组中,Bottom Sheet是悬浮弹窗,不能作为Scaffold的body页面组件使用 - 自定义的
showBottomSheet方法仅内部声明了布局函数,没有调用Flutter官方提供的弹窗API,所以不会触发弹窗 - 底部导航点击事件没有做分支判断,点击第四个选项时依然修改了当前页面下标,会导致body加载错误组件
修改步骤
- 移除页面数组中第四个无效的
showBottomSheet()元素,只保留前三个业务页面 - 修改底部导航的
onTap逻辑:点击下标为3的第四个选项时,不修改当前页面下标,直接调用弹窗方法 - 重写
showBottomSheet方法,调用官方showModalBottomSheetAPI加载你写的弹窗布局
修改后的完整代码
import 'package:flutter/material.dart'; class _MyNavigationBarState extends State<MyNavigationBar> { int _currentTabIndex = 0; @override Widget build(BuildContext context) { // 仅保留三个业务页面即可 final _kTabPages = <Widget>[ Page1(), Page2(), Page3(), ]; final _kBottmonNavBarItems = <BottomNavigationBarItem>[ const BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), const BottomNavigationBarItem(icon: Icon(Icons.network_cell), label: 'Prices'), const BottomNavigationBarItem(icon: Icon(Icons.add_circle), label: 'Trade'), const BottomNavigationBarItem(icon: Icon(Icons.account_balance_wallet), label: 'Wallet'), ]; final bottomNavBar = BottomNavigationBar( items: _kBottmonNavBarItems, currentIndex: _currentTabIndex, type: BottomNavigationBarType.fixed, onTap: (int index) { // 点击第四个选项时直接弹出底部弹窗,不切换当前页面 if (index == 3) { showCustomBottomSheet(context); return; } // 前三个选项正常切换页面 setState(() { _currentTabIndex = index; }); }, ); return Scaffold( body: _kTabPages[_currentTabIndex], bottomNavigationBar: bottomNavBar, ); } // 重写弹窗方法,调用官方Bottom Sheet API void showCustomBottomSheet(BuildContext context) { showModalBottomSheet( context: context, backgroundColor: Colors.transparent, isScrollControlled: true, builder: (BuildContext context) { return Container( height: 300, padding: const EdgeInsets.all(8.0), decoration: BoxDecoration( color: Colors.white, border: Border.all(color: Colors.blue, width: 2.0), borderRadius: BorderRadius.circular(8.0), ), child: ListView( children: <Widget>[ const ListTile(title: Text('Bottom sheet')), const TextField( keyboardType: TextInputType.number, decoration: InputDecoration( border: OutlineInputBorder(), icon: Icon(Icons.attach_money), labelText: 'Enter an integer', ), ), Container( alignment: Alignment.center, child: ElevatedButton.icon( icon: const Icon(Icons.save), label: const Text('Save and close'), onPressed: () => Navigator.pop(context), ), ) ], ), ); } ); } }
注意事项
- 弹窗布局要设置白色背景,否则会出现透明背景问题
isScrollControlled参数设为true可适配弹窗内输入框弹出时的布局偏移- 不需要保留之前的长度校验
assert逻辑,现在页面数组长度和导航项长度不需要完全一致
内容的提问来源于stack exchange,提问作者Tinovimba Mawoyo
相关产品推荐
相关产品推荐

