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
相关产品推荐
相关产品推荐

