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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 12:59:29