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

Flutter中如何为带CircularNotchedRectangle的BottomAppBar加圆角并保阴影

解决方案:带圆角、缺口且保留阴影的BottomAppBar

嘿,这个问题我太熟悉了!用ClipRRect包裹BottomAppBar确实会丢失阴影——因为Material组件的阴影是绘制在自身边界之外的,ClipRRect会把边界外的内容都裁剪掉,自然就看不到阴影了。

给你两个实用的解决方案,都能实现带圆角、圆形缺口且保留Material阴影的BottomAppBar:


方案一:用外层Material组件提供阴影和圆角(推荐)

这个方法最简洁,不需要自定义形状,只需要把BottomAppBar放在一个带圆角和阴影的Material组件内部,同时关闭BottomAppBar自身的阴影即可:

class BottomNavigationView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Transform.translate(
      offset: Offset(0.0, -10),
      child: Container(
        margin: EdgeInsets.only(left: 20, right: 20),
        // 外层Material负责提供阴影和圆角
        child: Material(
          elevation: 8.0, // 调整阴影强度,和原BottomAppBar一致即可
          borderRadius: BorderRadius.all(Radius.circular(30)),
          child: BottomAppBar(
            elevation: 0.0, // 关闭BottomAppBar自身的阴影
            shape: CircularNotchedRectangle(), // 保留圆形缺口
            child: Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                Column(
                  mainAxisSize: MainAxisSize.min,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Icon(Icons.accessibility_new),
                  ],
                ),
                _buildMiddleTabItem(),
                Column(
                  mainAxisSize: MainAxisSize.min,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Icon(Icons.accessibility_new),
                  ],
                )
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildMiddleTabItem() {
    return Expanded(
      child: SizedBox(
        height: 60,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            SizedBox(height: 24),
            Text(''),
          ],
        ),
      ),
    );
  }
}

原理说明:

  • 外层Material组件负责绘制圆角和阴影,它的边界是带圆角的,阴影会正确显示在圆角边界外
  • BottomAppBar只负责提供圆形缺口的形状,关闭自身的elevation避免重复阴影
  • 这种方法不需要修改原有BottomAppBar的结构,代码改动极小

方案二:自定义Shape同时实现圆角和缺口

如果希望BottomAppBar自身就具备圆角+缺口的形状,可以自定义一个NotchedShape,把CircularNotchedRectangle的缺口逻辑和圆角结合:

首先定义自定义形状:

class RoundCornerNotchedShape extends NotchedShape {
  final BorderRadius borderRadius;
  final CircularNotchedRectangle _innerNotch = CircularNotchedRectangle();

  RoundCornerNotchedShape({required this.borderRadius});

  @override
  Path getOuterPath(Rect host, Rect? guest) {
    // 先获取圆形缺口的路径
    final notchPath = _innerNotch.getOuterPath(host, guest);
    // 再创建一个带圆角的矩形路径
    final roundedRectPath = Path()
      ..addRRect(RRect.fromRectAndCorners(
        host,
        topLeft: borderRadius.topLeft,
        topRight: borderRadius.topRight,
        bottomLeft: borderRadius.bottomLeft,
        bottomRight: borderRadius.bottomRight,
      ));
    // 合并两个路径,取交集就是带圆角和缺口的形状
    return Path.combine(PathOperation.intersect, notchPath, roundedRectPath);
  }
}

然后修改BottomNavigationView使用这个自定义形状:

class BottomNavigationView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Transform.translate(
      offset: Offset(0.0, -10),
      child: Container(
        margin: EdgeInsets.only(left: 20, right: 20),
        child: BottomAppBar(
          elevation: 8.0, // 保留自身阴影
          // 使用自定义的圆角+缺口形状
          shape: RoundCornerNotchedShape(
            borderRadius: BorderRadius.all(Radius.circular(30)),
          ),
          child: Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              Column(
                mainAxisSize: MainAxisSize.min,
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Icon(Icons.accessibility_new),
                ],
              ),
              _buildMiddleTabItem(),
              Column(
                mainAxisSize: MainAxisSize.min,
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Icon(Icons.accessibility_new),
                ],
              )
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildMiddleTabItem() {
    return Expanded(
      child: SizedBox(
        height: 60,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            SizedBox(height: 24),
            Text(''),
          ],
        ),
      ),
    );
  }
}

原理说明:

  • 自定义RoundCornerNotchedShape同时实现了圆形缺口和圆角的路径计算
  • BottomAppBar使用这个形状后,自身的边界就是带圆角和缺口的,阴影会正确绘制在这个边界外,不需要任何裁剪

两种方案都能完美解决你的问题,个人更推荐方案一,代码更简洁易维护。

内容的提问来源于stack exchange,提问作者Da Artagnan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 14:07:43