Flutter中实现百分比环形进度组件的方案咨询
实现Flutter自定义环形百分比进度组件
直接用Flutter自带的CustomPainter就能实现完全自定义的环形进度组件,比第三方包更灵活,能精准匹配你的设计需求,以下是具体实现:
1. 自定义环形进度绘制器
创建RingProgressPainter类,负责绘制背景环、进度环和中间的百分比文字:
import 'dart:math'; import 'package:flutter/material.dart'; class RingProgressPainter extends CustomPainter { final double progress; // 0-1之间的进度值 final Color progressColor; final Color backgroundColor; final double strokeWidth; final TextStyle textStyle; RingProgressPainter({ required this.progress, required this.progressColor, required this.backgroundColor, required this.strokeWidth, required this.textStyle, }); @override void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); final radius = min(size.width, size.height) / 2 - strokeWidth / 2; // 绘制背景圆环 final backgroundPaint = Paint() ..color = backgroundColor ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..strokeCap = StrokeCap.round; // 可选:设置端点为圆角 canvas.drawCircle(center, radius, backgroundPaint); // 绘制进度圆环 final progressPaint = Paint() ..color = progressColor ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..strokeCap = StrokeCap.round; final arcAngle = 2 * pi * progress; canvas.drawArc( Rect.fromCircle(center: center, radius: radius), -pi / 2, // 从顶部开始绘制 arcAngle, false, progressPaint, ); // 绘制中间百分比文字 final text = '${(progress * 100).toInt()}%'; final textSpan = TextSpan(text: text, style: textStyle); final textPainter = TextPainter( text: textSpan, textAlign: TextAlign.center, textDirection: TextDirection.ltr, ); textPainter.layout(minWidth: 0, maxWidth: size.width); final textOffset = Offset( center.dx - textPainter.width / 2, center.dy - textPainter.height / 2, ); textPainter.paint(canvas, textOffset); } @override bool shouldRepaint(covariant RingProgressPainter oldDelegate) { return oldDelegate.progress != progress || oldDelegate.progressColor != progressColor || oldDelegate.backgroundColor != backgroundColor || oldDelegate.strokeWidth != strokeWidth || oldDelegate.textStyle != textStyle; } }
2. 封装成可复用组件
把绘制器包装成RingProgressWidget,方便在项目中调用:
class RingProgressWidget extends StatelessWidget { final double progress; final Color progressColor; final Color backgroundColor; final double strokeWidth; final TextStyle textStyle; final double size; const RingProgressWidget({ super.key, required this.progress, this.progressColor = Colors.blue, this.backgroundColor = Colors.grey.shade200, this.strokeWidth = 8.0, this.textStyle = const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), this.size = 120.0, }); @override Widget build(BuildContext context) { return SizedBox( width: size, height: size, child: CustomPaint( painter: RingProgressPainter( progress: progress.clamp(0.0, 1.0), // 确保进度值在0-1之间 progressColor: progressColor, backgroundColor: backgroundColor, strokeWidth: strokeWidth, textStyle: textStyle, ), ), ); } }
3. 使用示例
在页面中直接调用这个组件,比如展示75%的进度:
class ProgressPage extends StatelessWidget { const ProgressPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('环形进度示例')), body: const Center( child: RingProgressWidget( progress: 0.75, progressColor: Colors.green, strokeWidth: 10.0, textStyle: TextStyle(fontSize: 28, color: Colors.green), size: 150.0, ), ), ); } }
自定义说明
- 调整
strokeWidth可改变圆环粗细 - 修改
strokeCap可设置圆环端点为圆角或直角 - 自定义
progressColor和backgroundColor匹配设计风格 - 调整
textStyle可修改百分比文字的大小、颜色和字体
内容的提问来源于stack exchange,提问作者mahdi tabatabaie
相关产品推荐
相关产品推荐

