You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter自定义BottomNavigationBar无法切换页面求助

Flutter自定义BottomNavigationBar无法触发页面切换的解决方案

问题根源

自定义BottomNavigationBar后底部按钮点击无响应,核心原因是Stack组件的层级遮挡:

  • 原代码中包含IconButton的Container位于FAB之后,导致该容器覆盖在所有可点击元素上方,拦截了点击事件
  • 多余的floatingActionButtonLocation配置与集成在bottomNavigationBar中的FAB冲突
  • Container高度超出父容器范围,进一步加剧了遮挡问题

修复方案

  1. 调整Stack子Widget顺序,将IconButton所在容器移至FAB之前,确保FAB处于最上层可被点击
  2. 移除冗余的floatingActionButtonLocation配置
  3. 统一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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 22:07:03