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

Flutter图表绘制求助:新手尝试多款Floating库未成功绘制目标图表

实现目标环形图表方案

方案一:用flutter_circular_chart快速实现

  1. 先在pubspec.yaml添加依赖:
dependencies:
  flutter_circular_chart: ^0.1.0
  1. 核心代码示例:
import 'package:flutter/material.dart';
import 'package:flutter_circular_chart/flutter_circular_chart.dart';

class CustomRingChart extends StatefulWidget {
  @override
  _CustomRingChartState createState() => _CustomRingChartState();
}

class _CustomRingChartState extends State<CustomRingChart> {
  final GlobalKey<AnimatedCircularChartState> _chartKey = GlobalKey();
  final List<CircularStackEntry> _data = [
    CircularStackEntry(
      [
        CircularSegmentEntry(60, Colors.blue, rankKey: 'completed'),
        CircularSegmentEntry(40, Colors.grey[300]!, rankKey: 'remaining'),
      ],
      rankKey: 'progress',
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.center,
      children: [
        AnimatedCircularChart(
          key: _chartKey,
          size: const Size(200, 200),
          initialChartData: _data,
          chartType: CircularChartType.Ring,
          ringStrokeWidth: 30,
        ),
        Text(
          '60%',
          style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
        ),
        Positioned(
          bottom: -20,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Row(
                children: [
                  Container(width: 12, height: 12, color: Colors.blue),
                  SizedBox(width: 4),
                  Text('已完成'),
                ],
              ),
              SizedBox(width: 40),
              Row(
                children: [
                  Container(width: 12, height: 12, color: Colors.grey[300]),
                  SizedBox(width: 4),
                  Text('未完成'),
                ],
              ),
            ],
          ),
        ),
      ],
    );
  }
}

方案二:自定义CustomPaint实现(更灵活)

如果现成库满足不了细节需求,直接自定义绘制:

import 'package:flutter/material.dart';

class CustomRingChart extends StatelessWidget {
  final double progress; // 传入0-1的进度值

  const CustomRingChart({super.key, required this.progress});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 200,
      height: 220,
      child: Stack(
        alignment: Alignment.center,
        children: [
          CustomPaint(
            size: const Size(200, 200),
            painter: _RingPainter(progress: progress),
          ),
          Text(
            '${(progress * 100).toInt()}%',
            style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
          ),
          Positioned(
            bottom: 0,
            child: Row(
              children: [
                _LegendItem(color: Colors.blue, label: '已完成'),
                const SizedBox(width: 40),
                _LegendItem(color: Colors.grey[300]!, label: '未完成'),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _RingPainter extends CustomPainter {
  final double progress;

  _RingPainter({required this.progress});

  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    final radius = size.width / 2 - 15;
    final strokeWidth = 30.0;

    // 绘制背景环
    final backgroundPaint = Paint()
      ..color = Colors.grey[300]!
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round;
    canvas.drawCircle(center, radius, backgroundPaint);

    // 绘制进度环
    final progressPaint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round;
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius),
      -0.5 * 3.1416, // 从顶部开始绘制
      2 * 3.1416 * progress, // 扫过的角度
      false,
      progressPaint,
    );
  }

  @override
  bool shouldRepaint(covariant _RingPainter oldDelegate) {
    return oldDelegate.progress != progress;
  }
}

class _LegendItem extends StatelessWidget {
  final Color color;
  final String label;

  const _LegendItem({required this.color, required this.label});

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Container(
          width: 12,
          height: 12,
          decoration: BoxDecoration(
            color: color,
            borderRadius: BorderRadius.circular(2),
          ),
        ),
        const SizedBox(width: 4),
        Text(label),
      ],
    );
  }
}

使用时直接调用:CustomRingChart(progress: 0.6)

注意事项

  • 动态更新进度的话,方案一用setState更新_data里的数值,方案二直接更新progress参数即可
  • 可以根据需求调整环的颜色、宽度、整体大小、标签位置等细节

内容的提问来源于stack exchange,提问作者DaoDao

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 17:05:20