Flutter如何实现带中心文字的自定义圆形进度指示器?
在Flutter中实现带中心文本的自定义圆形进度指示器
嗨,我来帮你搞定这个需求~原生的CircularProgressIndicator确实不支持直接在中心加文本,但我们可以通过叠加组件或者自定义绘制两种方式轻松实现,下面给你详细讲两种方案:
方法一:基于原生组件快速实现(低成本)
这种方式最省心,直接用Stack把原生进度圈和文本叠在一起,保留原生组件的样式特性:
class TextCircularProgress extends StatelessWidget { final double progress; // 0-1的进度值 final String centerText; final Color? progressColor; final double strokeWidth; final TextStyle? textStyle; const TextCircularProgress({ super.key, required this.progress, required this.centerText, this.progressColor, this.strokeWidth = 4.0, this.textStyle, }); @override Widget build(BuildContext context) { return Stack( alignment: Alignment.center, // 让文本居中在进度圈上 children: [ // 原生圆形进度指示器 CircularProgressIndicator( value: progress, strokeWidth: strokeWidth, valueColor: progressColor != null ? AlwaysStoppedAnimation(progressColor!) : null, backgroundColor: Colors.grey.shade200, ), // 中心文本 Text( centerText, style: textStyle ?? const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black87, ), ), ], ); } }
使用示例
// 显示60%的进度 TextCircularProgress( progress: 0.6, centerText: "60%", progressColor: Colors.blue, strokeWidth: 6.0, )
方法二:自定义Painter实现高度定制
如果需要更个性化的效果(比如进度条圆角、渐变颜色、特殊轨迹),可以用CustomPainter完全自定义绘制逻辑:
class CustomTextProgressCircle extends StatefulWidget { final double progress; final String centerText; final Color progressColor; final Color bgColor; final double strokeWidth; final TextStyle textStyle; const CustomTextProgressCircle({ super.key, required this.progress, required this.centerText, this.progressColor = Colors.green, this.bgColor = Colors.grey.shade300, this.strokeWidth = 8.0, required this.textStyle, }); @override State<CustomTextProgressCircle> createState() => _CustomTextProgressCircleState(); } class _CustomTextProgressCircleState extends State<CustomTextProgressCircle> { @override Widget build(BuildContext context) { return CustomPaint( painter: _ProgressCirclePainter( progress: widget.progress, progressColor: widget.progressColor, bgColor: widget.bgColor, strokeWidth: widget.strokeWidth, ), child: Center(child: Text(widget.centerText, style: widget.textStyle)), ); } } // 自定义绘制逻辑 class _ProgressCirclePainter extends CustomPainter { final double progress; final Color progressColor; final Color bgColor; final double strokeWidth; _ProgressCirclePainter({ required this.progress, required this.progressColor, required this.bgColor, required this.strokeWidth, }); @override void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); final radius = (size.width - strokeWidth) / 2; // 绘制背景圆环 final bgPaint = Paint() ..color = bgColor ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..strokeCap = StrokeCap.round; // 进度条两端设为圆角 canvas.drawCircle(center, radius, bgPaint); // 绘制进度圆环 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, ); } @override bool shouldRepaint(_ProgressCirclePainter oldDelegate) { return oldDelegate.progress != progress || oldDelegate.progressColor != progressColor || oldDelegate.strokeWidth != strokeWidth; } }
使用示例
CustomTextProgressCircle( progress: 0.75, centerText: "75%", progressColor: Colors.orange, bgColor: Colors.grey.shade200, strokeWidth: 10.0, textStyle: const TextStyle( fontSize: 22, fontWeight: FontWeight.w600, color: Colors.deepOrange, ), )
两种方案任选其一就行,第一种适合快速开发,第二种适合需要个性化样式的场景~
内容的提问来源于stack exchange,提问作者Musa Usman
相关产品推荐
相关产品推荐

