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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 22:32:20