如何重启Flutter的TweenAnimation?按钮/文本变更时重启动画
解决方案
1. 解决LateInitializationError与vsync参数问题
要使用AnimationController,你需要:
- 让你的
State类混入SingleTickerProviderStateMixin(单动画控制器场景),当前State实例就能作为vsync参数的提供者,避免动画在后台无效消耗资源。 - 在
initState方法中主动初始化AnimationController,不能仅用late修饰却不完成初始化。
2. 实现文本变更/按钮点击时重启模糊动画
- 按钮点击:直接调用动画控制器的
reset()+forward()方法重启动画。 - 文本变更:通过
didUpdateWidget对比新旧widget的文本值,或者用ValueListenableBuilder监听文本变量,一旦变化就触发动画重启。
完整代码示例
import 'dart:ui'; import 'package:flutter/material.dart'; class BlurTextAnimation extends StatefulWidget { final String customText; const BlurTextAnimation({super.key, required this.customText}); @override State<BlurTextAnimation> createState() => _BlurTextAnimationState(); } // 混入SingleTickerProviderStateMixin提供vsync支持 class _BlurTextAnimationState extends State<BlurTextAnimation> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _blurAnimation; @override void initState() { super.initState(); // 初始化动画控制器,vsync传入当前State实例 _controller = AnimationController( duration: const Duration(milliseconds: 1500), vsync: this, ); // 创建模糊度动画:从0到5再回到0 _blurAnimation = Tween<double>(begin: 0, end: 5).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), )..addStatusListener((status) { if (status == AnimationStatus.completed) { _controller.reverse(); } }); // 初始执行一次动画 _controller.forward(); } // 监听文本变更,自动重启动画 @override void didUpdateWidget(covariant BlurTextAnimation oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.customText != widget.customText) { _restartAnimation(); } } // 封装重启动画的方法,按钮点击直接调用 void _restartAnimation() { _controller.reset(); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 用AnimatedBuilder构建模糊文本 AnimatedBuilder( animation: _blurAnimation, builder: (context, child) { return BackdropFilter( filter: ImageFilter.blur( sigmaX: _blurAnimation.value, sigmaY: _blurAnimation.value, ), child: child, ); }, child: Text( widget.customText, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ), ), const SizedBox(height: 20), ElevatedButton( onPressed: _restartAnimation, child: const Text('重新执行动画'), ), ], ); } } // 使用示例 void main() { runApp(const MaterialApp(home: HomePage())); } class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { String _text = '初始文本'; void _changeText() { setState(() { _text = '文本已变更 ${DateTime.now().second}'; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('文本模糊动画')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ BlurTextAnimation(customText: _text), const SizedBox(height: 20), ElevatedButton( onPressed: _changeText, child: const Text('修改文本'), ), ], ), ), ); } }
代码说明
SingleTickerProviderStateMixin:为AnimationController提供vsync,确保动画仅在组件可见时运行。didUpdateWidget:对比新旧文本值,文本变更时自动重启动画。_restartAnimation:封装重置并启动动画的逻辑,按钮点击和文本变更场景可复用。BackdropFilter:配合AnimatedBuilder实现文本模糊效果的动态更新。
内容的提问来源于stack exchange,提问作者My Name
相关产品推荐
相关产品推荐

