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

Flutter开发中如何实现如下图所示的反向border-radius效果

Flutter 实现反向border-radius(内凹圆角)的方案

反向圆角指的是边角向内凹陷的圆角效果,Flutter原生没有直接提供对应的组件属性,可通过以下两种常用方案实现:

方案1:原生自定义裁剪实现(无第三方依赖)

通过CustomClipper结合ClipPath手动绘制带反向圆角的路径,灵活性最高,可自定义任意位置的反向圆角:

  • 第一步:定义自定义裁剪器和角位枚举
enum Corner {
  topLeft,
  topRight,
  bottomLeft,
  bottomRight
}

class InvertedRadiusClipper extends CustomClipper<Path> {
  final double radius;
  final List<Corner> corners;

  InvertedRadiusClipper({
    required this.radius, 
    this.corners = const [Corner.topLeft, Corner.topRight, Corner.bottomLeft, Corner.bottomRight]
  });

  @override
  Path getClip(Size size) {
    final path = Path();
    // 定位到左上角反向圆角起点
    path.moveTo(0, radius);
    // 绘制左上角反向圆角
    if (corners.contains(Corner.topLeft)) {
      path.arcToPoint(Offset(radius, 0), radius: Radius.circular(radius), clockwise: false);
    } else {
      path.lineTo(0, 0);
      path.lineTo(radius, 0);
    }
    // 上边缘到右上角反向圆角起点
    path.lineTo(size.width - radius, 0);
    // 绘制右上角反向圆角
    if (corners.contains(Corner.topRight)) {
      path.arcToPoint(Offset(size.width, radius), radius: Radius.circular(radius), clockwise: false);
    } else {
      path.lineTo(size.width, 0);
      path.lineTo(size.width, radius);
    }
    // 右边缘到右下角反向圆角起点
    path.lineTo(size.width, size.height - radius);
    // 绘制右下角反向圆角
    if (corners.contains(Corner.bottomRight)) {
      path.arcToPoint(Offset(size.width - radius, size.height), radius: Radius.circular(radius), clockwise: false);
    } else {
      path.lineTo(size.width, size.height);
      path.lineTo(size.width - radius, size.height);
    }
    // 下边缘到左下角反向圆角起点
    path.lineTo(radius, size.height);
    // 绘制左下角反向圆角
    if (corners.contains(Corner.bottomLeft)) {
      path.arcToPoint(Offset(0, size.height - radius), radius: Radius.circular(radius), clockwise: false);
    } else {
      path.lineTo(0, size.height);
      path.lineTo(0, size.height - radius);
    }
    path.close();
    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return oldClipper is InvertedRadiusClipper && (oldClipper.radius != radius || oldClipper.corners != corners);
  }
}
  • 第二步:用裁剪器包裹目标组件即可生效
ClipPath(
  clipper: InvertedRadiusClipper(radius: 16, corners: [Corner.topLeft, Corner.bottomRight]),
  child: Container(
    width: 300,
    height: 200,
    color: Colors.blue,
  ),
)

如果需要添加边框,可配合CustomPaint在对应路径上绘制描边即可。

方案2:借助第三方库快速实现

如果不需要高度自定义,可直接使用成熟的第三方库inner_border_radius,无需手动编写路径逻辑:

  1. 先在pubspec.yaml中添加依赖
dependencies:
  inner_border_radius: ^最新版本号
  1. 直接给Container的decoration赋值即可
Container(
  width: 300,
  height: 200,
  decoration: BoxDecoration(
    color: Colors.blue,
    borderRadius: InnerBorderRadius.only(
      topLeft: Radius.circular(16),
      bottomRight: Radius.circular(16),
    ),
  ),
)

注意事项

  • 反向圆角无法直接使用Flutter原生BoxShadow添加阴影,需要自定义阴影绘制逻辑,或配合Shadow属性绑定自定义ShapeBorder实现。
  • 如需在反向圆角位置添加透明镂空效果,可将ClipPath嵌套在Stack中,底层放背景内容即可。

内容的提问来源于stack exchange,提问作者Ibrahim 7

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 03:57:03