Flutter如何实现顺序执行的进度条动画并在完成时触发回调函数
Flutter 多进度条序列动画实现方案
以下是修改后可直接运行的完整代码,已经实现你要求的3个进度条顺序执行、循环播放、每个进度完成可触发回调的需求:
import 'package:flutter/material.dart'; class AnimationTest3 extends StatefulWidget { const AnimationTest3({Key? key}) : super(key: key); @override _AnimationTest3State createState() => _AnimationTest3State(); } class _AnimationTest3State extends State<AnimationTest3> with TickerProviderStateMixin { late AnimationController _controller; late Animation<double> _progress1Anim; late Animation<double> _progress2Anim; late Animation<double> _progress3Anim; // 回调触发标记,避免同一轮动画重复触发回调 bool _firstFinished = false; bool _secondFinished = false; bool _thirdFinished = false; // 自定义回调函数,可根据需求替换为你的业务逻辑(比如播放音节) void _onFirstProgressEnd() { debugPrint("第一个进度条完成,触发播放第一个音节"); } void _onSecondProgressEnd() { debugPrint("第二个进度条完成,触发播放第二个音节"); } void _onThirdProgressEnd() { debugPrint("第三个进度条完成,触发播放第三个音节"); } @override void initState() { super.initState(); // 总动画时长=3个进度条各自时长之和:3s*3=9s _controller = AnimationController(vsync: this, duration: const Duration(seconds: 9)); // 拆分总动画时长,每个进度条对应1/3的总时间区间 _progress1Anim = Tween<double>(begin: 0, end: 1).animate( CurvedAnimation(parent: _controller, curve: const Interval(0.0, 1/3, curve: Curves.linear)) ); _progress2Anim = Tween<double>(begin: 0, end: 1).animate( CurvedAnimation(parent: _controller, curve: const Interval(1/3, 2/3, curve: Curves.linear)) ); _progress3Anim = Tween<double>(begin: 0, end: 1).animate( CurvedAnimation(parent: _controller, curve: const Interval(2/3, 1.0, curve: Curves.linear)) ); // 监听动画进度,触发对应回调 _controller.addListener(() { setState(() {}); final value = _controller.value; if (value >= 1/3 && !_firstFinished) { _firstFinished = true; _onFirstProgressEnd(); } else if (value >= 2/3 && !_secondFinished) { _secondFinished = true; _onSecondProgressEnd(); } else if (value >= 1.0 && !_thirdFinished) { _thirdFinished = true; _onThirdProgressEnd(); } }); // 监听动画完成状态,重置后自动循环播放 _controller.addStatusListener((status) { if (status == AnimationStatus.completed) { _firstFinished = false; _secondFinished = false; _thirdFinished = false; _controller.reset(); _controller.forward(); } }); // 启动动画 _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( // 如果你项目中没有NavMenu组件可以注释掉下面这行 // drawer: Drawer(child: NavMenu()), appBar: AppBar(title: const Text("Animation Test 3"), elevation: 0), body: LayoutBuilder( builder: (context, constraints) { return Column(children: [ Container( height: constraints.maxHeight * 0.3, color: Colors.indigo[50]), Container(height: constraints.maxHeight * 0.4, color: Colors.white), Container( height: constraints.maxHeight * 0.3, color: Colors.indigo[50], child: LayoutBuilder( builder: (context, constraints) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 进度条1 Container( padding: const EdgeInsets.symmetric(horizontal: 2.0), height: 4, width: constraints.maxWidth * 1 / 3, child: LinearProgressIndicator(value: _progress1Anim.value), ), // 进度条2 Container( padding: const EdgeInsets.symmetric(horizontal: 2.0), height: 4, width: constraints.maxWidth * 1 / 3, child: LinearProgressIndicator(value: _progress2Anim.value), ), // 进度条3 Container( padding: const EdgeInsets.symmetric(horizontal: 2.0), height: 4, width: constraints.maxWidth * 1 / 3, child: LinearProgressIndicator(value: _progress3Anim.value), ), ], ); }, ), ) ]); }, ), ); } }
关键逻辑说明
- 单个动画控制器管理全流程:总时长设置为3个进度条的动画时长之和,通过
Interval曲线拆分时间区间,天然实现进度条的顺序执行,无需多个控制器互相监听 - 线性动画适配进度条需求:
Curves.linear保证进度条匀速增长,符合等待时长提示的使用场景 - 回调触发标记避免重复调用:同轮动画中每个回调仅触发一次,符合业务逻辑要求
- 自动循环实现:动画完成后自动重置状态并重启,无需手动干预
内容的提问来源于stack exchange,提问作者Ian Rajkumar
相关产品推荐
相关产品推荐

