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

Flutter中如何创建带圆角的自定义四边形?能否通过绘制顶点指定圆角半径?

当然可以通过指定顶点坐标+设置圆角半径的方式实现这种自定义带圆角的四边形!我帮你整理了一套完整的实现方案,包括思路、代码和细节注意点,你可以直接参考使用:

核心实现思路

要实现这种自定义形状,我们主要依靠Flutter的CustomPainter和Path类:

  • 先定义四边形的四个顶点坐标,确保它们按顺时针或逆时针顺序排列
  • 对于每个顶点的圆角,不用直接用直线连接顶点,而是用Path.arcToPoint方法绘制圆弧过渡,这样就能精准控制每个角的圆角半径
  • 最后闭合路径,填充颜色并绘制边框(如果需要的话)
完整代码示例

第一步:自定义Painter类

这个类负责绘制带圆角的四边形,你可以灵活调整顶点、圆角大小、颜色等参数:

class RoundedQuadrilateralPainter extends CustomPainter {
  final List<Offset> vertices;
  final double borderRadius;
  final Color fillColor;
  final Color strokeColor;
  final double strokeWidth;

  RoundedQuadrilateralPainter({
    required this.vertices,
    this.borderRadius = 8.0,
    this.fillColor = Colors.blue,
    this.strokeColor = Colors.black,
    this.strokeWidth = 2.0,
  }) : assert(vertices.length == 4, "必须传入4个顶点坐标");

  @override
  void paint(Canvas canvas, Size size) {
    // 初始化填充画笔
    final fillPaint = Paint()
      ..color = fillColor
      ..style = PaintingStyle.fill;

    final path = Path();
    // 移动到第一个顶点的右侧偏移位置,准备绘制第一个圆角
    path.moveTo(vertices[0].dx + borderRadius, vertices[0].dy);

    // 绘制第一个圆角:从第一个顶点右侧到第二个顶点上方
    path.arcToPoint(
      Offset(vertices[1].dx, vertices[1].dy - borderRadius),
      radius: Radius.circular(borderRadius),
      clockwise: false,
    );
    // 绘制第二个顶点到圆角结束点的直线
    path.lineTo(vertices[1].dx, vertices[1].dy + borderRadius);

    // 绘制第二个圆角:从第二个顶点下方到第三个顶点左侧
    path.arcToPoint(
      Offset(vertices[2].dx - borderRadius, vertices[2].dy),
      radius: Radius.circular(borderRadius),
      clockwise: false,
    );
    // 绘制第三个顶点到圆角结束点的直线
    path.lineTo(vertices[2].dx + borderRadius, vertices[2].dy);

    // 绘制第三个圆角:从第三个顶点右侧到第四个顶点下方
    path.arcToPoint(
      Offset(vertices[3].dx, vertices[3].dy + borderRadius),
      radius: Radius.circular(borderRadius),
      clockwise: false,
    );
    // 绘制第四个顶点到圆角结束点的直线
    path.lineTo(vertices[3].dx, vertices[3].dy - borderRadius);

    // 绘制第四个圆角:从第四个顶点上方回到第一个顶点左侧,闭合路径
    path.arcToPoint(
      Offset(vertices[0].dx - borderRadius, vertices[0].dy),
      radius: Radius.circular(borderRadius),
      clockwise: false,
    );

    path.close();

    // 绘制填充区域
    canvas.drawPath(path, fillPaint);

    // 如果需要边框,绘制边框
    if (strokeWidth > 0) {
      final strokePaint = Paint()
        ..color = strokeColor
        ..style = PaintingStyle.stroke
        ..strokeWidth = strokeWidth;
      canvas.drawPath(path, strokePaint);
    }
  }

  @override
  bool shouldRepaint(covariant RoundedQuadrilateralPainter oldDelegate) {
    // 当参数变化时重绘
    return oldDelegate.vertices != vertices ||
        oldDelegate.borderRadius != borderRadius ||
        oldDelegate.fillColor != fillColor ||
        oldDelegate.strokeColor != strokeColor ||
        oldDelegate.strokeWidth != strokeWidth;
  }
}

第二步:在Widget中使用这个Painter

你只需要调整vertices里的坐标值,就能匹配参考图片的形状:

class CustomQuadrilateralScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 根据参考图片调整这四个顶点的坐标
    final quadVertices = [
      Offset(60, 30),
      Offset(280, 60),
      Offset(240, 210),
      Offset(40, 190),
    ];

    return Scaffold(
      appBar: AppBar(title: const Text("自定义圆角四边形")),
      body: Center(
        child: CustomPaint(
          size: const Size(320, 250),
          painter: RoundedQuadrilateralPainter(
            vertices: quadVertices,
            borderRadius: 15.0, // 调整圆角大小匹配参考图
            fillColor: Colors.lightBlueAccent,
            strokeColor: Colors.blue.shade700,
            strokeWidth: 3.0,
          ),
        ),
      ),
    );
  }
}
关键细节提示
  • 顶点顺序:一定要保证四个顶点是按顺时针或逆时针连续排列的,否则路径会出现混乱,圆角方向也会出错
  • 单独调整圆角:如果某个角不需要圆角,你可以给这个角单独设置borderRadius为0,或者直接用lineTo代替对应的arcToPoint方法
  • 适配参考图:你可以通过调整quadVertices里的四个Offset值,让四边形的形状完全匹配参考图片,再微调borderRadius就能达到一模一样的效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:12:15