| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- 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<AnimatedGradientProgressBar>
- with TickerProviderStateMixin {
- late AnimationController _controller;
- late Animation<double> _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<double>(
- 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,
- ),
- ),
- ),
- );
- },
- ),
- ],
- ),
- ),
- ),
- ],
- );
- }
- }
|