You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 12:48:03