import 'package:flutter/material.dart'; import 'dart:math'; import 'dart:async'; typedef DownTimeEndListener = void Function(); /// Description: splash 倒计时图标 /// Time : 08/17/2023 Thursday /// Author : liuyuqi.gov@msn.cn class DownTimeWidget extends StatefulWidget { DownTimeWidget( {Key? key, required this.clors, required this.width, required this.strokeWidth, required this.time, required this.textStyle, required this.endListener}); Color clors; double width; double strokeWidth; int time; TextStyle textStyle; DownTimeEndListener endListener; @override State createState() => DownTimeState(); } class DownTimeState extends State with TickerProviderStateMixin { late AnimationController controller; late CurvedAnimation curvedAnimation; late Tween animationTween; double angle = 0; late Animation animation; int _time = 0; @override void initState() { super.initState(); _time = (widget.time / 1000).toInt(); controller = AnimationController( vsync: this, duration: Duration(milliseconds: widget.time)); curvedAnimation = CurvedAnimation(parent: controller, curve: Curves.linear); animationTween = Tween(begin: 0.0, end: 360.0); animation = animationTween.animate(curvedAnimation); animation.addStatusListener((status) { if (status == AnimationStatus.completed) { widget.endListener(); } }); animation.addListener(() { angle = animation.value; setState(() {}); }); controller.forward(); } @override void dispose() { controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Container( width: widget.width, height: widget.width, decoration: BoxDecoration( borderRadius: BorderRadius.circular(widget.width / 2), color: Colors.white), child: Stack( children: [ Center( child: DownTimeText( time: _time, textStyle: widget.textStyle, ), ), CustomPaint( painter: DrawArcPainter( colors: widget.clors, angle: angle, width: widget.width, ), ), ], ), ); } } class DrawArcPainter extends CustomPainter { DrawArcPainter( {required this.colors, required this.angle, required this.width, required this.mStrokeWidth}); Color colors; double mStrokeWidth; double width; double angle; double angleToRadian(double angle) => angle * (pi / 180.0); double radianToAngle(double radian) => radian * (180.0 / pi); @override void paint(Canvas canvas, Size size) { Paint paint = Paint() ..color = colors == null ? Colors.red : colors ..strokeWidth = mStrokeWidth == null ? 2.0 : mStrokeWidth ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.round; Rect rect = Rect.fromLTWH(0.0, 0.0, width, width); canvas.drawArc(rect, 0.0, angleToRadian(angle), false, paint); } @override bool shouldRepaint(CustomPainter oldDelegate) { return true; } } class DownTimeText extends StatefulWidget { DownTimeText({Key? key, required this.time, required this.textStyle}) : super(key: key); int time; TextStyle textStyle; @override State createState() => DownTimeTextState(); } class DownTimeTextState extends State { DownTimeTextState(); int _time; Timer timer; @override void initState() { super.initState(); _time = widget.time; startDownTimer(); } void startDownTimer() { timer = Timer.periodic(Duration(seconds: 1), (time) { if (_time == null || _time == 0) { setState(() {}); timer.cancel(); return; } _time--; setState(() {}); }); } @override void dispose() { timer.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Text( "倒计时:$_time", style: widget.textStyle, ); } }