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

如何用Flutter实现附件所示的带居中停靠按钮的底部导航栏

解决方案:实现带居中悬浮按钮的底部导航栏

核心问题修复与功能实现

你的问题主要集中在底部导航栏的裁剪路径错误和缺少导航项选中状态管理,以下是完整的实现方案:


1. 修正底部导航栏的裁剪路径

替换原有的CurveDraw类,直接绘制符合需求的底部凹陷路径,避免旋转导致的坐标混乱:

class CurveDraw extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    final double sw = size.width;
    final double sh = size.height;
    final double fabDiameter = 60; // 与悬浮按钮尺寸对应

    Path path = Path();
    // 从左下角开始绘制
    path.moveTo(0, sh);
    // 左侧圆角
    path.quadraticBezierTo(0, 0, sh / 2, 0);
    // 画到悬浮按钮左侧位置
    path.lineTo(sw / 2 - fabDiameter / 2 - 10, 0);
    // 绘制悬浮按钮下方的凹陷曲线
    path.quadraticBezierTo(
      sw / 2 - fabDiameter / 2,
      0,
      sw / 2 - fabDiameter / 2,
      sh / 2,
    );
    path.lineTo(sw / 2 + fabDiameter / 2, sh / 2);
    path.quadraticBezierTo(
      sw / 2 + fabDiameter / 2,
      0,
      sw / 2 + fabDiameter / 2 + 10,
      0,
    );
    // 右侧圆角
    path.lineTo(sw - sh / 2, 0);
    path.quadraticBezierTo(sw, 0, sw, sh);
    // 闭合路径
    path.lineTo(0, sh);
    path.close();

    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}

2. 实现导航项点击变色逻辑

通过状态变量跟踪选中的导航项,点击时更新状态并切换图标颜色:

class _BottomNavDemoState extends State<BottomNavDemo> {
  int _selectedIndex = 0;

  // 更新选中导航项的状态
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color(0xFFFFFFFF),
      bottomNavigationBar: Material(
        color: Colors.transparent,
        elevation: 100,
        child: ClipPath(
          clipper: CurveDraw(),
          child: Container(
            height: 100,
            color: Colors.white,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                IconButton(
                  icon: Icon(
                    Icons.home,
                    size: 30,
                    color: _selectedIndex == 0 ? Colors.deepPurple : Colors.black54,
                  ),
                  onPressed: () => _onItemTapped(0),
                ),
                IconButton(
                  icon: Icon(
                    Icons.branding_watermark,
                    size: 30,
                    color: _selectedIndex == 1 ? Colors.deepPurple : Colors.black54,
                  ),
                  onPressed: () => _onItemTapped(1),
                ),
                // 留空区域匹配悬浮按钮位置
                SizedBox(width: 60),
                IconButton(
                  icon: Icon(
                    Icons.cloud_download,
                    size: 30,
                    color: _selectedIndex == 2 ? Colors.deepPurple : Colors.black54,
                  ),
                  onPressed: () => _onItemTapped(2),
                ),
                IconButton(
                  icon: Icon(
                    Icons.face,
                    size: 30,
                    color: _selectedIndex == 3 ? Colors.deepPurple : Colors.black54,
                  ),
                  onPressed: () => _onItemTapped(3),
                ),
              ],
            ),
          ),
        ),
      ),
      floatingActionButton: MaterialButton(
        color: Colors.deepPurple,
        padding: EdgeInsets.all(15),
        onPressed: () {},
        shape: CircleBorder(),
        child: Icon(
          Icons.add,
          size: 35,
          color: Colors.white,
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    );
  }
}

class BottomNavDemo extends StatefulWidget {
  @override
  _BottomNavDemoState createState() => _BottomNavDemoState();
}

关键说明

  • 路径修正:直接从底部开始绘制路径,避免旋转导致的坐标错位,确保悬浮按钮下方的凹陷与按钮尺寸完全匹配。
  • 选中状态管理:通过_selectedIndex变量控制图标颜色,点击时调用setState更新UI,实现点击变色效果。
  • 布局对齐:中间的SizedBox宽度与悬浮按钮直径一致,保证导航项与悬浮按钮的位置精准对齐。

内容的提问来源于stack exchange,提问作者Frank Slayer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 07:40:26