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

请求实现自定义半圆形进度条效果,ClipRect无法满足需求

实现半圆形进度条的替代方案(替代ClipRect)

ClipRect仅支持矩形区域裁剪,要实现半圆形进度条,推荐以下两种适配方案,结合你已有的素材或灵活定制样式:

方案一:用ClipPath搭配现有素材

通过自定义裁剪路径,对彩色进度条素材进行动态裁剪,叠加在背景条上方:

  1. 自定义半圆形裁剪器,接收进度值动态生成裁剪范围:
import 'dart:math' as math;
import 'package:flutter/material.dart';

class SemiCircleClipper extends CustomClipper<Path> {
  final double progress; // 0-1之间的进度值

  SemiCircleClipper(this.progress);

  @override
  Path getClip(Size size) {
    final path = Path();
    // 适配下半圆素材:裁剪区域为从左到右的半圆部分
    final arcRect = Rect.fromLTWH(0, size.height / 2, size.width, size.height);
    // 起始角度180°(π弧度),扫过角度随进度变化(0-180°对应0-1进度)
    path.addArc(arcRect, math.pi, math.pi * progress);
    // 闭合路径确保裁剪区域完整
    path.lineTo(size.width, size.height);
    path.lineTo(0, size.height);
    path.close();
    return path;
  }

  @override
  bool shouldReclip(covariant SemiCircleClipper oldClipper) {
    return oldClipper.progress != progress;
  }
}
  1. 在UI中叠加素材并应用裁剪:
Stack(
  alignment: Alignment.center,
  children: [
    // 半圆形背景条素材
    Image.asset('assets/semi_circle_bg.png'),
    // 彩色进度条素材,通过ClipPath裁剪出对应进度的区域
    ClipPath(
      clipper: SemiCircleClipper(0.6), // 传入0.6代表60%进度
      child: Image.asset('assets/semi_circle_fill.png'),
    ),
  ],
)

提示:如果你的素材是上半圆,只需调整addArc的起始角度为0(0°),扫过角度范围保持0到π即可。

方案二:自定义Canvas绘制(摆脱素材限制)

如果需要更灵活的样式调整,直接通过Canvas绘制半圆形进度条,无需依赖外部素材:

import 'dart:math' as math;
import 'package:flutter/material.dart';

class SemiCircleProgressPainter extends CustomPainter {
  final double progress;
  final Color bgColor;
  final Color fillColor;
  final double strokeWidth;

  SemiCircleProgressPainter({
    required this.progress,
    required this.bgColor,
    required this.fillColor,
    this.strokeWidth = 12,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    final radius = (size.width / 2) - (strokeWidth / 2);

    // 绘制背景半圆
    final bgPaint = Paint()
      ..color = bgColor
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round; // 可选:设置端点圆角
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius),
      math.pi,
      math.pi,
      false,
      bgPaint,
    );

    // 绘制进度半圆
    final fillPaint = Paint()
      ..color = fillColor
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round;
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius),
      math.pi,
      math.pi * progress,
      false,
      fillPaint,
    );
  }

  @override
  bool shouldRepaint(covariant SemiCircleProgressPainter oldDelegate) {
    return oldDelegate.progress != progress;
  }
}

使用时通过CustomPaint组件渲染:

CustomPaint(
  size: const Size(200, 100), // 宽为半圆直径,高为半圆半径
  painter: SemiCircleProgressPainter(
    progress: 0.75,
    bgColor: Colors.grey.shade300,
    fillColor: Colors.orange,
  ),
)

内容的提问来源于stack exchange,提问作者Veins of Games

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 09:05:22