绘制:
import 'package:jade/utils/JadeColors.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'package:flutter_screenutil/flutter_screenutil.dart';
class ArcProgressBar extends StatefulWidget{
const ArcProgressBar({Key key}) : super(key: key);
State<StatefulWidget> createState() {
// TODO: implement createState
return _ArcProgressBar();
}
}
class _ArcProgressBar extends State<ArcProgressBar> with TickerProviderStateMixin{
AnimationController controller;
void initState() {
// TODO: implement initState
super.initState();
controller = AnimationController(duration:const Duration(seconds: 1),lowerBound:0,upperBound:60,vsync: this);
controller.addListener(() {
setState(() {
// print(controller.value);
});
});
controller.forward();
}
void dispose() {
// TODO: implement dispose
controller.dispose();
super.dispose();
}
Widget build(BuildContext context) {
// TODO: implement build
return CustomPaint(
painter: TestArcPainter(
bgColor: JadeColors.lightGrey,
sweepColor: Color(0xffFFC10F),
strokeWidth: 45.0,
progress: controller.value / 100),
size: const Size(180.0,180.0), // 调整大小以适应你的需求
);
}
}
class TestArcPainter extends CustomPainter{
///进度百分比
double progress;
///弧线宽度
double strokeWidth;
///背景颜色
Color bgColor;
///进度条颜色
Color sweepColor;
//整圆弧度
final double wholeCirclesRadian=6.283185307179586;
//圆被分割为160份
final int tableCount= 12;
TestArcPainter({
this.strokeWidth,
this.bgColor,
this.sweepColor,
this.progress});
void paint(Canvas canvas, Size size) {
// TODO: implement paint
double cx = size.width / 2;
double cy = size.height / 2;
Paint _paint = Paint();
// ..color = Colors.red
// ..strokeWidth = 5;
//
// canvas.drawCircle(Offset(cx,cy), 2, _paint);
// canvas.save();
_paint = Paint()
..color = bgColor
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.butt;
double startDegree = degToRad(210);
double sweepDegree = degToRad(120);
Rect _rect = Rect.fromLTWH(0, 0, size.width, size.height);
canvas.drawArc(_rect, startDegree, sweepDegree, false, _paint);
canvas.save();
canvas.restore();
_paint = Paint()
..color = sweepColor
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.butt;
canvas.drawArc(_rect, startDegree, sweepDegree * progress, false, _paint);
canvas.save();
//计算三角函数公式 X= 圆中心点x + 半径 * cos(角度*3.14/180)
//y=圆中心点y + 半径 * sin(角度*3.14/180)
_paint
..color = Color(0xffF27800)
..style = PaintingStyle.fill
..strokeWidth = 3;
double deg = startDegree + sweepDegree * progress;
double x = cx + (cx + strokeWidth / 2) * math.cos(deg);
double y = cy + (cy +strokeWidth / 2) * math.sin(deg );
// canvas.drawLine(Offset(cx, cy), Offset(x, y), _paint); //从圆形开始绘制的指针
double x1 = cx + (cx - strokeWidth / 2) * math.cos(deg);
double y1 = cy + (cy -strokeWidth / 2) * math.sin(deg );
canvas.drawLine(Offset(x1, y1), Offset(x, y), _paint); //从圆形开始绘制的指针
canvas.restore();
TextPainter textPainterCenter = TextPainter(
text: TextSpan(children: [
TextSpan(text: '¥', style: TextStyle(color: Colors.black,fontSize:40.sp)),
TextSpan(text: '370.00', style: TextStyle(color: Colors.black,fontSize:66.sp,fontWeight: FontWeight.bold))
]),
textDirection: TextDirection.ltr,
);
textPainterCenter.layout();
textPainterCenter.paint(canvas, Offset(cx - (textPainterCenter.size.width / 2), cy - (textPainterCenter.size.height / 2)));
canvas.save();
canvas.restore();
TextPainter textPainterCenterTwo = TextPainter(
text: TextSpan(
children: [
TextSpan(text: '剩余金额', style: TextStyle(color: JadeColors.grey,fontSize:24.sp)),
TextSpan(text: '(已退款)', style: TextStyle(color: JadeColors.orange_4,fontSize:24.sp)),
]
),
textDirection: TextDirection.ltr,
);
textPainterCenterTwo.layout();
textPainterCenterTwo.paint(canvas, Offset(cx - (textPainterCenterTwo.size.width / 2), cy + textPainterCenterTwo.size.height * 1.5));
canvas.save();
canvas.restore();
double tableSpace = wholeCirclesRadian/tableCount;
double textLeftX = cx + cx * math.cos(startDegree);
double textLeftY = cy + cy * math.sin(startDegree) ;
TextPainter textPainterLeft = TextPainter(
text: TextSpan(text: '¥120000.00', style: TextStyle(color: JadeColors.grey,fontSize: 20.sp)),
textDirection: TextDirection.ltr,
);
textPainterLeft.textDirection = TextDirection.ltr;
textPainterLeft.layout();
canvas.rotate(tableSpace);
textPainterLeft.paint(canvas, Offset(textLeftX - (textPainterLeft.size.width / 8), textLeftY - (textPainterLeft.size.height / 2)));
canvas.save();
canvas.restore();
double textRightX = cx + cx * math.cos(startDegree + sweepDegree);
double textRightY = cy + cy * math.sin(startDegree + sweepDegree) ;
TextPainter textPainterRight = TextPainter(
text: TextSpan(text: '¥1200000.00', style: TextStyle(color: JadeColors.grey,fontSize: 20.sp)),
textDirection: TextDirection.ltr,
);
textPainterRight.layout();
canvas.rotate(-(wholeCirclesRadian / 6));
textPainterRight.paint(canvas, Offset(textRightX - textPainterRight.size.width * 1.2, textRightY + (textPainterRight.size.height * 6.4) ));
canvas.save();
canvas.restore();
/*
ui.ParagraphBuilder paragraphBuilder = ui.ParagraphBuilder(ui.ParagraphStyle())..pushStyle(ui.TextStyle(color: Colors.black))..addText('100');
ui.ParagraphConstraints paragraphConstraints = ui.ParagraphConstraints(width: size.width);
ui.Paragraph paragraph = paragraphBuilder.build() ..layout(paragraphConstraints);
canvas.drawParagraph(paragraph, Offset(cx - (textPainterCenter.size.width / 2), cy - (textPainterCenter.size.height / 2)));
*/
}
/// 角度转换弧度
double degToRad(double deg) => deg * (math.pi / 180.0);
bool shouldRepaint(covariant CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}
引用:(单纯绘制,相应数据未作处理)
Container(
child: ArcProgressBar(),
color: Colors.white
)