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

如何在Flutter中实现带中间弧形的BottomNavigationBar?

如何实现带有中间弧形的Flutter底部导航栏?

我目前用以下代码实现了顶部圆角的底部导航栏:

Container(
        decoration: const BoxDecoration(
          borderRadius: BorderRadius.only(
              topRight: Radius.circular(30), topLeft: Radius.circular(30)),
          boxShadow: [
            BoxShadow(color: Colors.black38, spreadRadius: 0, blurRadius: 10),
          ],
        ),
        child: ClipRRect(
          borderRadius: const BorderRadius.only(
            topLeft: Radius.circular(30.0),
            topRight: Radius.circular(30.0),
          ),
          child: BottomNavigationBar(
            type: BottomNavigationBarType.fixed,
            backgroundColor: Colors.transparent,
            selectedItemColor: Colors.purple,
            unselectedItemColor: Colors.grey,
            currentIndex: widget.selectedIndex,
            onTap: widget.onTap,
            items: widget.items,
          ),
        ))

当前效果:
当前效果

期望效果:
期望效果

请问有没有方法实现这种中间带有弧形的底部导航栏?


可以通过Stack组件结合CustomPainter实现该效果,具体步骤如下:

1. 自定义弧形背景绘制类

创建继承自CustomPainter的类,绘制带顶部圆角和中间下凹弧形的背景:

class CurvedNavBarPainter extends CustomPainter {
  final Color color;
  final double curveRadius;

  CurvedNavBarPainter({required this.color, required this.curveRadius});

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()..color = color;

    // 构建路径:顶部左右圆角 + 中间下凹弧形
    Path path = Path()
      ..moveTo(0, curveRadius)
      ..quadraticBezierTo(0, 0, curveRadius, 0) // 左上角圆角
      ..lineTo(size.width / 2 - curveRadius * 1.5, 0)
      ..quadraticBezierTo(
          size.width / 2, 0 - curveRadius, size.width / 2 + curveRadius * 1.5, 0) // 中间下凹弧形
      ..lineTo(size.width - curveRadius, 0)
      ..quadraticBezierTo(size.width, 0, size.width, curveRadius) // 右上角圆角
      ..lineTo(size.width, size.height)
      ..lineTo(0, size.height)
      ..close();

    canvas.drawPath(path, paint);

    // 绘制阴影
    Paint shadowPaint = Paint()
      ..color = Colors.black38
      ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 10);
    canvas.drawPath(path, shadowPaint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

2. 组合Stack实现完整导航栏

用Stack叠加自定义背景和BottomNavigationBar,同时调整内边距避开弧形区域:

Stack(
  alignment: Alignment.bottomCenter,
  children: [
    // 自定义弧形背景
    CustomPaint(
      size: Size(MediaQuery.of(context).size.width, 80),
      painter: CurvedNavBarPainter(
        color: Colors.white, // 背景色
        curveRadius: 30, // 弧形半径
      ),
    ),
    // 底部导航栏
    Padding(
      padding: const EdgeInsets.only(top: 15), // 顶部内边距避开弧形
      child: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        backgroundColor: Colors.transparent,
        elevation: 0, // 去掉默认阴影避免冲突
        selectedItemColor: Colors.purple,
        unselectedItemColor: Colors.grey,
        currentIndex: widget.selectedIndex,
        onTap: widget.onTap,
        items: widget.items,
      ),
    ),
  ],
)

关键说明

  • 用CustomPainter精确控制背景路径,比BorderRadius更灵活
  • 设置BottomNavigationBar的elevation: 0,避免默认阴影和自定义阴影冲突
  • 顶部内边距可根据弧形半径调整,确保中间图标不被遮挡

内容的提问来源于stack exchange,提问作者Henni Kent

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:47:03