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

Flutter中使用Paint在Row内绘制圆形并调整布局位置的问题

解决Flutter右下角圆形进度布局的位置问题

问题根源

  1. CustomPaint绘制坐标错误:你在CircleProgress里用了固定的Offset(100.w, 35.h)作为圆心,这会让圆形脱离CustomPaint的容器范围,导致位置完全失控。
  2. 布局结构未做定位:当前的Row直接放在Container里,没有设置右下角的定位逻辑,自然无法把元素放到目标位置。

修复步骤及代码

1. 修正CustomPaint的绘制逻辑

让圆形的绘制基于自身容器的尺寸,而不是外部固定值:

class CircleProgress extends CustomPainter {
  int done;
  int total;

  CircleProgress({required this.total, required this.done});

  final strokeWidth = 8.0;

  @override
  void paint(Canvas canvas, Size size) {
    Paint totalCircle = Paint()
      ..strokeWidth = strokeWidth
      ..color = const Color(0xFF8989BE)
      ..style = PaintingStyle.stroke;

    Paint doneCircle = Paint()
      ..strokeWidth = strokeWidth
      ..color = const Color(0xFFDFDFFD).withOpacity(0.96)
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round;

    // 基于CustomPaint自身尺寸计算圆心和半径,避免超出容器
    Offset center = Offset(size.width / 2, size.height / 2);
    double radius = (min(size.width, size.height) / 2) - (strokeWidth / 2);
    double angle = 2 * pi * (done / total);

    canvas.drawCircle(center, radius, totalCircle);
    // 从顶部开始绘制圆弧(pi/2对应12点钟方向)
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius),
      pi / 2,
      angle,
      false,
      doneCircle,
    );
  }

  @override
  bool shouldRepaint(covariant CircleProgress oldDelegate) {
    return oldDelegate.done != done || oldDelegate.total != total;
  }
}

注意:补全shouldRepaint方法,否则进度更新时不会重绘。

2. 调整外层布局,实现右下角定位

用Align组件将包含圆形和文本的Row定位到容器右下角,同时调整元素间距:

Container(
  // 父容器需设置合适宽高,让右下角定位生效
  width: double.infinity,
  height: 200.h, // 根据实际需求调整高度
  child: Align(
    alignment: Alignment.bottomRight,
    child: Padding(
      padding: EdgeInsets.only(bottom: 10.h, right: 10.w), // 调整边距避免贴边
      child: Row(
        mainAxisSize: MainAxisSize.min, // 让Row只占用所需宽度
        children: [
          CustomPaint(
            foregroundPainter: CircleProgress(done: 3, total: 4),
            size: Size(40.r, 40.r), // 调整圆形的大小
            child: Center(child: Text("3/4")), // 可把进度文本放回
          ),
          SizedBox(width: 5.w), // 给圆形和文本加间距
          Text("Weeks"),
        ],
      ),
    ),
  ),
)

关键说明

  • 使用Align(alignment: Alignment.bottomRight)直接将子组件定位到父容器右下角
  • Row设置mainAxisSize: MainAxisSize.min避免占用过多宽度
  • 用Padding调整右下角元素与容器边缘的距离,避免视觉拥挤
  • CustomPaint的尺寸通过size属性控制,内部绘制完全基于自身尺寸,确保位置可控

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 09:43:59