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

Flutter 如何创建价格标签形状的Box容器与边角裁剪卡片视图

Flutter实现价格标签容器与缺口裁剪卡片的方案

这两种不规则容器都可以通过Flutter自带的ClipPath组件结合自定义CustomClipper<Path>实现,无需引入第三方依赖,灵活度最高。

一、缺口边角裁剪卡片实现(对应示例效果)

边角裁剪卡片示例

自定义裁剪类代码

// 自定义卡片边角缺口裁剪器
class CardNotchClipper extends CustomClipper<Path> {
  // 缺口半径,可自定义
  final double notchRadius;
  // 缺口距离左上角的偏移量,可自定义
  final double notchOffset;

  CardNotchClipper({this.notchRadius = 12, this.notchOffset = 40});

  @override
  Path getClip(Size size) {
    final path = Path();
    // 起点:左上角缺口右侧
    path.moveTo(notchOffset + notchRadius, 0);
    // 顶边到右上角
    path.lineTo(size.width, 0);
    // 右上角圆角
    path.arcToPoint(Offset(size.width, 16), radius: const Radius.circular(16));
    // 右边到右下角
    path.lineTo(size.width, size.height);
    // 左下角圆角
    path.arcToPoint(Offset(0, size.height), radius: const Radius.circular(16));
    // 左边到缺口下方
    path.lineTo(0, notchOffset + notchRadius);
    // 画半圆缺口
    path.arcToPoint(Offset(0, notchOffset - notchRadius), radius: Radius.circular(notchRadius), clockwise: false);
    // 左边到左上角缺口左侧
    path.lineTo(0, 0);
    path.lineTo(notchOffset - notchRadius, 0);
    // 闭合缺口半圆
    path.arcToPoint(Offset(notchOffset + notchRadius, 0), radius: Radius.circular(notchRadius), clockwise: false);
    path.close();
    return path;
  }

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

使用方法

ClipPath(
  clipper: CardNotchClipper(notchRadius: 10, notchOffset: 50),
  child: Container(
    width: 300,
    height: 150,
    color: Colors.white,
    padding: const EdgeInsets.all(16),
    child: const Text("你的卡片内容"),
  ),
)

二、价格标签形状容器实现

自定义裁剪类代码

class PriceTagClipper extends CustomClipper<Path> {
  final double notchRadius;
  final double tagRadius;

  PriceTagClipper({this.notchRadius = 8, this.tagRadius = 8});

  @override
  Path getClip(Size size) {
    Path path = Path();
    path.lineTo(size.width - tagRadius, 0);
    path.arcToPoint(Offset(size.width, tagRadius), radius: Radius.circular(tagRadius));
    path.lineTo(size.width, size.height/2 - notchRadius);
    path.arcToPoint(Offset(size.width, size.height/2 + notchRadius), radius: Radius.circular(notchRadius), clockwise: false);
    path.lineTo(size.width, size.height - tagRadius);
    path.arcToPoint(Offset(size.width - tagRadius, size.height), radius: Radius.circular(tagRadius));
    path.lineTo(tagRadius, size.height);
    path.arcToPoint(Offset(0, size.height - tagRadius), radius: Radius.circular(tagRadius));
    path.lineTo(0, tagRadius);
    path.arcToPoint(Offset(tagRadius, 0), radius: Radius.circular(tagRadius));
    path.close();
    return path;
  }

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

使用方法和上述卡片一致,将ClipPath的clipper参数替换为PriceTagClipper即可。

注意事项

  • 可以自行修改Path的点位、圆角半径、缺口位置来适配你需要的样式
  • 如果需要给裁剪后的容器加阴影,不要直接给Container加elevation或者boxShadow,会被ClipPath裁剪掉,建议使用CustomPaint同时绘制阴影和自定义路径
  • 列表中大量使用这类自定义裁剪组件时,建议根据实际场景调整shouldReclip返回值,避免不必要的重绘

内容的提问来源于stack exchange,提问作者LIJU DANIEL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 11:15:04