import 'package:flutter/material.dart'; /// 支持动画过渡和渐变色的进度条 // 使用示例 // AnimatedGradientProgressBar( // targetValue: 0.75, // gradient: LinearGradient(colors: [Colors.orange, Colors.red]), // height: 10, // borderRadius: 5, // ) class AnimatedGradientProgressBar extends StatefulWidget { // 目标进度值(0~1) final double targetValue; // 动画时长 final Duration duration; // 渐变色 final Gradient gradient; // 进度条高度 final double height; // 圆角半径 final double borderRadius; const AnimatedGradientProgressBar({ super.key, required this.targetValue, required this.duration, required this.gradient, this.height = 10.0, this.borderRadius = 7.0, }); @override AnimatedGradientProgressBarState createState() => AnimatedGradientProgressBarState(); } class AnimatedGradientProgressBarState extends State with TickerProviderStateMixin { late AnimationController _controller; late Animation _animation; @override void initState() { super.initState(); _controller = AnimationController(duration: widget.duration, vsync: this); _animation = CurvedAnimation(parent: _controller, curve: Curves.easeInOut); _startAnimation(); } @override void didUpdateWidget(AnimatedGradientProgressBar oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.targetValue != widget.targetValue) { _resetAnimation(); _startAnimation(); } } @override void dispose() { // 移除监听 _animation.removeListener(() {}); _controller.dispose(); super.dispose(); } void _startAnimation() { print('进度条 => 初始动画值: ${_animation.value}'); // 0.0 // 先移除旧监听 _animation.removeListener(() {}); // 创建新的 Tween 动画 _animation = Tween( begin: 0, end: widget.targetValue, ).animate(_animation); // 添加监听器并启动动画 _animation.addListener(() => setState(() {})); _controller.forward(); Future.delayed(widget.duration, () { print('进度条 => 最终动画值: ${_animation.value}'); }); } void _resetAnimation() => _controller.reset(); @override Widget build(BuildContext context) { return Stack( // 允许子组件溢出自己本身的大小,默认是裁切的 clipBehavior: Clip.none, children: [ // 百分比文本 Positioned( right: 0, // 文字位于进度条上方 bottom: widget.height + 4, child: AnimatedBuilder( animation: _animation, builder: (context, _) { return Text( '${(_animation.value * 100).toStringAsFixed(0)}%', style: const TextStyle(fontSize: 12, color: Colors.black54), ); }, ), ), // 进度条 ClipRRect( borderRadius: BorderRadius.circular(widget.borderRadius), child: Container( width: double.infinity, height: widget.height, decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(widget.borderRadius), ), child: Stack( children: [ AnimatedBuilder( animation: _animation, builder: (context, _) { return FractionallySizedBox( widthFactor: _animation.value, alignment: Alignment.centerLeft, child: Container( decoration: BoxDecoration( gradient: widget.gradient, borderRadius: BorderRadius.circular( widget.borderRadius, ), ), ), ); }, ), ], ), ), ), ], ); } }