Flutter自定义BottomNavigationBar无法切换页面求助
问题根源
自定义BottomNavigationBar后底部按钮点击无响应,核心原因是Stack组件的层级遮挡:
- 原代码中包含IconButton的
Container位于FAB之后,导致该容器覆盖在所有可点击元素上方,拦截了点击事件 - 多余的
floatingActionButtonLocation配置与集成在bottomNavigationBar中的FAB冲突 - Container高度超出父容器范围,进一步加剧了遮挡问题
修复方案
- 调整Stack子Widget顺序,将IconButton所在容器移至FAB之前,确保FAB处于最上层可被点击
- 移除冗余的
floatingActionButtonLocation配置 - 统一Container高度与父容器一致,避免超出区域的异常遮挡
修改后的完整代码
class MainScreenScaffold3 extends StatefulWidget { const MainScreenScaffold3({Key? key}) : super(key: key); @override State<MainScreenScaffold3> createState() => _MainScreenScaffold3State(); } bool value = false; class _MainScreenScaffold3State extends State<MainScreenScaffold3> { late List<Map<String, Object>> _pages; int _selectedPageIndex = 2; @override void initState() { _pages = [ {'page': Abilities()}, {'page': Education()}, {'page': HomePage()}, {'page': Employment()}, {'page': About()}, ]; super.initState(); } void _selectPage(int index) { setState(() { _selectedPageIndex = index; }); } bool _onTap = false; @override Widget build(BuildContext context) { final themeState = Provider.of<DarkThemeProvider>(context); return Scaffold( appBar: AppBar( toolbarHeight: 40, backgroundColor: Theme.of(context).brightness == Brightness.dark ? navigationBarsDMColor : navigationBarsLMColor, elevation: Theme.of(context).brightness == Brightness.dark ? 0.0 : 3.0, actions: <Widget>[ IconButton( icon: FaIcon( themeState.darkTheme ? FontAwesomeIcons.lightbulb : FontAwesomeIcons.lightbulb, size: 20, color: _onTap ? Colors.black : Colors.white), tooltip: 'Light/Dark Mode', onPressed: () { themeState.darkTheme = value; setState(() { value = !value; _onTap = !_onTap; }); }, ), ], leading: Builder( builder: (context) => IconButton( onPressed: () { Scaffold.of(context).openDrawer(); }, icon: FaIcon( themeState.darkTheme ? FontAwesomeIcons.bars : FontAwesomeIcons.bars, size: 20, color: _onTap ? Colors.black : Colors.white), tooltip: 'Quick Look', color: Colors.grey, ), ), centerTitle: true, title: AnimatedCapsuleButton( onPressed: () { // Open the webpage here }, darkModeColor: yellowDMColor, lightModeColor: yellowLMColor, text: 'Resume', ), ), drawer: SkillsPageDrawer(), body: _pages[_selectedPageIndex]['page'] as Widget, bottomNavigationBar: Stack( children: [ Positioned( bottom: 0, left: 0, child: Container( width: MediaQuery.of(context).size.width, height: 90, child: Stack( clipBehavior: Clip.none, children: [ CustomPaint( size: Size(MediaQuery.of(context).size.width, 90), painter: BNBCustomPainter(), ), // 调整:将IconButton容器移至FAB之前,避免遮挡 Container( width: MediaQuery.of(context).size.width, // 调整:高度与父容器一致,避免超出遮挡 height: 90, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Padding( padding: const EdgeInsets.fromLTRB(150, 0, 0, 0), child: Container( decoration: BoxDecoration( shape: BoxShape.circle, color: Theme.of(context).brightness == Brightness.dark ? orangeDMColor : orangeLMColor, ), child: IconButton( icon: Icon(Icons.bar_chart, color: Colors.white), onPressed: () => _selectPage(0), tooltip: 'Abilities', ), ), ), Container( decoration: BoxDecoration( shape: BoxShape.circle, color: Theme.of(context).brightness == Brightness.dark ? greenDMColor : greenLMColor, ), child: IconButton( icon: Icon(Icons.school, color: Colors.white), onPressed: () => _selectPage(1), tooltip: 'Education', ), ), SizedBox( width: MediaQuery.of(context).size.width * 0.20, ), Container( decoration: BoxDecoration( shape: BoxShape.circle, color: Theme.of(context).brightness == Brightness.dark ? purpleDMColor : purpleLMColor, ), child: IconButton( icon: Icon(Icons.work, color: Colors.white), onPressed: () => _selectPage(3), tooltip: 'Employments', ), ), Padding( padding: const EdgeInsets.fromLTRB(0, 0, 150, 0), child: Container( decoration: BoxDecoration( shape: BoxShape.circle, color: Theme.of(context).brightness == Brightness.dark ? magentaDMColor : magentaLMColor, ), child: IconButton( icon: Icon(Icons.person, color: Colors.white), onPressed: () => _selectPage(4), tooltip: 'About', ), ), ), ], ), ), // FAB移至最后,确保在最上层 Center( heightFactor: 0.7, child: FloatingActionButton( backgroundColor: Theme.of(context).brightness == Brightness.dark ? blueDMColor : blueLMColor, child: FaIcon( themeState.darkTheme ? FontAwesomeIcons.houseChimney : FontAwesomeIcons.houseChimney, color: _onTap ? Colors.white : Colors.white), elevation: 0.1, onPressed: () => setState(() { _selectedPageIndex = 2; }), ), ), ], ), ), ), ], ), // 移除:冗余的floatingActionButtonLocation配置 ); } } class BNBCustomPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { Paint paint = new Paint() ..color = Colors.green ..style = PaintingStyle.fill; Path path = Path(); path.moveTo(0, 30); // Start path.quadraticBezierTo(size.width * 0.20, 0, size.width * 0.40, 0); path.quadraticBezierTo(size.width * 0.45, 0, size.width * 0.45, 20); path.arcToPoint(Offset(size.width * 0.55, 20), radius: Radius.circular(20.0), clockwise: false); path.quadraticBezierTo(size.width * 0.55, 0, size.width * 0.65, 0); path.quadraticBezierTo(size.width * 0.80, 0, size.width, 30); path.lineTo(size.width, size.height); path.lineTo(0, size.height); path.lineTo(0, 30); canvas.drawShadow(path, Colors.black, 5, true); canvas.drawPath(path, paint); } @override bool shouldRepaint(CustomPainter oldDelegate) { return false; } }
内容的提问来源于stack exchange,提问作者kajunkenny
相关产品推荐
相关产品推荐

