请求实现自定义半圆形进度条效果,ClipRect无法满足需求
实现半圆形进度条的替代方案(替代ClipRect)
ClipRect仅支持矩形区域裁剪,要实现半圆形进度条,推荐以下两种适配方案,结合你已有的素材或灵活定制样式:
方案一:用ClipPath搭配现有素材
通过自定义裁剪路径,对彩色进度条素材进行动态裁剪,叠加在背景条上方:
- 自定义半圆形裁剪器,接收进度值动态生成裁剪范围:
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; } }
- 在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
相关产品推荐
相关产品推荐

