Flutter中实现多颜色分段环形/半环形进度指示器的方案咨询
Flutter中实现多颜色分段环形/半环形进度指示器的方案咨询
嗨~我懂你想要的是那种带多颜色分段的环形(或半环形)进度指示器,既要灵活又要实现起来省心对吧?刚好有几个靠谱的方案可以推荐给你,不用完全从零手写所有代码哦!
方案一:用成熟第三方包快速实现
如果不想自己写复杂的绘制逻辑,第三方包是最省心的选择,比如syncfusion_flutter_charts,它支持自定义分段颜色、进度占比,还能轻松切换全环/半环模式:
首先在pubspec.yaml里添加依赖:
dependencies: syncfusion_flutter_charts: ^25.2.0
然后用下面的示例代码快速搭建:
import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_charts/charts.dart'; class SegmentedProgressPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: SfCircularChart( series: <CircularSeries>[ DoughnutSeries<SegmentData, String>( dataSource: [ SegmentData('红色段', 30, Colors.red), SegmentData('蓝色段', 20, Colors.blue), SegmentData('绿色段', 25, Colors.green), SegmentData('黄色段', 25, Colors.yellow), ], xValueMapper: (SegmentData data, _) => data.name, yValueMapper: (SegmentData data, _) => data.value, pointColorMapper: (SegmentData data, _) => data.color, // 改成 startAngle:180, endAngle:0 就是半环形 startAngle: 0, endAngle: 360, innerRadius: '70%', // 控制环形的粗细 ) ], ), ), ); } } class SegmentData { final String name; final double value; final Color color; SegmentData(this.name, this.value, this.color); }
这个包的配置项非常丰富,还能添加标签、调整端点样式,完全能满足灵活定制的需求。
方案二:自定义CustomPainter实现高度定制
如果第三方包的样式不能完全匹配你的预期,那用CustomPainter手动绘制也不难,而且能实现100%的自定义:
import 'package:flutter/material.dart'; import 'dart:math'; class SegmentedProgressPainter extends CustomPainter { final List<Segment> segments; final double strokeWidth; final bool isHalfCircle; SegmentedProgressPainter({ required this.segments, this.strokeWidth = 20, this.isHalfCircle = true, }); @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 startAngle = isHalfCircle ? pi : 0; final totalAngle = isHalfCircle ? pi : 2 * pi; final totalValue = segments.fold(0.0, (sum, seg) => sum + seg.value); double currentAngle = startAngle; for (var segment in segments) { final sweepAngle = (segment.value / totalValue) * totalAngle; final paint = Paint() ..color = segment.color ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..strokeCap = StrokeCap.round; // 可选:把端点改成圆角 canvas.drawArc( Rect.fromCircle(center: center, radius: radius), currentAngle, sweepAngle, false, paint, ); currentAngle += sweepAngle; } } @override bool shouldRepaint(covariant CustomPainter oldDelegate) { return oldDelegate != this; } } class Segment { final double value; final Color color; Segment(this.value, this.color); } // 使用示例 class CustomProgressPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: CustomPaint( size: Size(200, 200), painter: SegmentedProgressPainter( segments: [ Segment(30, Colors.red), Segment(20, Colors.blue), Segment(25, Colors.green), Segment(25, Colors.yellow), ], isHalfCircle: true, // 改成false就是全环形 ), ), ), ); } }
这种方式你可以完全掌控每一段的颜色、粗细、动画效果,甚至可以给进度添加加载动画,只需要配合AnimationController就能实现。
这两种方案都能完美实现你想要的效果,如果你追求开发速度,第三方包是首选;如果需要极致定制,自定义Painter就非常适合。
内容来源于stack exchange
相关产品推荐
相关产品推荐

