Flutter图表绘制求助:新手尝试多款Floating库未成功绘制目标图表
实现目标环形图表方案
方案一:用flutter_circular_chart快速实现
- 先在
pubspec.yaml添加依赖:
dependencies: flutter_circular_chart: ^0.1.0
- 核心代码示例:
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
相关产品推荐
相关产品推荐

