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

如何在Flutter中使用Custom Painter实现附图中的自定义形状

使用Flutter CustomPainter实现顶部凹陷的自定义形状

要实现附图中顶部带圆弧凹陷、四周带圆角的自定义形状,你可以通过自定义CustomPainter构建路径并绘制,具体实现如下:

1. 定义CustomPainter子类

这个类负责构建形状路径并绘制,支持配置填充色、圆角大小和凹陷圆弧半径:

class CustomNotchedShapePainter extends CustomPainter {
  final Color fillColor;
  final double borderRadius;
  final double notchRadius;

  CustomNotchedShapePainter({
    required this.fillColor,
    this.borderRadius = 16.0,
    this.notchRadius = 24.0,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = fillColor
      ..style = PaintingStyle.fill;

    final path = Path();
    final centerX = size.width / 2;

    // 绘制左下角圆角
    path.moveTo(borderRadius, size.height);
    path.arcToPoint(
      Offset(0, size.height - borderRadius),
      radius: Radius.circular(borderRadius),
      clockwise: false,
    );

    // 左侧边到左上角圆角
    path.lineTo(0, borderRadius);
    path.arcToPoint(
      Offset(borderRadius, 0),
      radius: Radius.circular(borderRadius),
      clockwise: false,
    );

    // 顶部左侧到凹陷左端点
    path.lineTo(centerX - notchRadius, 0);

    // 绘制顶部中间的凹陷圆弧(向下弯曲)
    path.arcToPoint(
      Offset(centerX + notchRadius, 0),
      radius: Radius.circular(notchRadius),
      clockwise: false,
    );

    // 顶部右侧到右上角圆角
    path.lineTo(size.width - borderRadius, 0);
    path.arcToPoint(
      Offset(size.width, borderRadius),
      radius: Radius.circular(borderRadius),
      clockwise: false,
    );

    // 右侧边到右下角圆角
    path.lineTo(size.width, size.height - borderRadius);
    path.arcToPoint(
      Offset(size.width - borderRadius, size.height),
      radius: Radius.circular(borderRadius),
      clockwise: false,
    );

    // 闭合路径完成形状
    path.close();

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomNotchedShapePainter oldDelegate) {
    return oldDelegate.fillColor != fillColor ||
        oldDelegate.borderRadius != borderRadius ||
        oldDelegate.notchRadius != notchRadius;
  }
}

2. 使用自定义Painter

在Widget中通过CustomPaint组件调用这个Painter:

class CustomShapeDemo extends StatelessWidget {
  const CustomShapeDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 300,
      height: 200,
      child: CustomPaint(
        painter: CustomNotchedShapePainter(
          fillColor: Colors.blueAccent,
          borderRadius: 16,
          notchRadius: 28,
        ),
      ),
    );
  }
}

关键细节说明

  • 路径构建逻辑:从左下角开始按顺时针方向绘制,顶部中间通过arcToPoint并设置clockwise: false,让圆弧向下凹陷形成缺口。
  • 可配置参数:通过borderRadius调整整体圆角大小,notchRadius控制顶部凹陷的弧度,可根据需求灵活修改。
  • 性能优化:shouldRepaint方法仅在颜色或参数变化时触发重绘,避免不必要的性能消耗。

如果需要添加边框,只需新增一个Paint对象,设置style: PaintingStyle.stroke和strokeWidth,再用相同路径绘制一次即可。

内容的提问来源于stack exchange,提问作者Muhammad Usama Akbar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 15:48:47