如何在Flutter中使用CustomPainter实现线条单端圆角?
实现线条两端差异化样式(一端圆角一端方形)
Flutter 的 strokeCap 属性确实只能统一设置线条两端的样式,要实现一端圆角、一端方形的效果,你可以用以下两种方式解决:
方法一:基础线条+单独绘制圆角端
先绘制一段两端为方形的基础线条,再在需要圆角的端点位置,绘制一个和线条同宽同色的圆形,模拟圆角效果。
修改后的代码如下:
import 'package:flutter/material.dart'; class LinePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final height = size.height; final width = size.width; final strokeWidth = 20.0; final startPoint = Offset(width * 0.25, height / 2); final endPoint = Offset(width * 0.75, height / 2); // 绘制两端为方形的基础直线 final linePaint = Paint() ..color = Colors.red ..strokeWidth = strokeWidth ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.square; canvas.drawLine(startPoint, endPoint, linePaint); // 在起点绘制圆形,模拟圆角效果 final circlePaint = Paint() ..color = Colors.red; canvas.drawCircle(startPoint, strokeWidth / 2, circlePaint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) { return false; } } class Example extends StatefulWidget { const Example({Key? key}) : super(key: key); @override State<Example> createState() => _ExampleState(); } class _ExampleState extends State<Example> with SingleTickerProviderStateMixin { @override Widget build(BuildContext context) { return Scaffold( body: CustomPaint( painter: LinePainter(), child: Container(), ), ); } }
方法二:用Path拼接自定义形状
通过 Path 的圆弧和直线拼接,构建出一端圆角、一端方形的闭合路径,再用填充模式绘制。
代码示例:
import 'package:flutter/material.dart'; import 'dart:math' as math; class LinePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final height = size.height; final width = size.width; final strokeWidth = 20.0; final radius = strokeWidth / 2; final startPoint = Offset(width * 0.25, height / 2); final endPoint = Offset(width * 0.75, height / 2); final path = Path(); // 从起点右侧开始绘制直线到终点 path.moveTo(startPoint.dx + radius, startPoint.dy); path.lineTo(endPoint.dx, endPoint.dy); // 向下延伸终点的方形端 path.lineTo(endPoint.dx, endPoint.dy + radius); // 向左绘制到起点下方位置 path.lineTo(startPoint.dx - radius, endPoint.dy + radius); // 绘制左上角的圆弧回到起点右侧 path.addArc( Rect.fromCircle(center: startPoint, radius: radius), 0.5 * math.pi, math.pi, ); path.close(); final paint = Paint() ..color = Colors.red ..style = PaintingStyle.fill; canvas.drawPath(path, paint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) { return false; } } // Widget代码同上...
两种方法对比:
- 方法一简单直观,适合纯直线的场景;
- 方法二适配更复杂的路径需求,通过Path拼接实现自定义形状。
内容的提问来源于stack exchange,提问作者Kdon
相关产品推荐
相关产品推荐

