Dart Flutter:如何从ScopedModel触发其子Widget的动画?
实现Flutter方块的渐隐消失效果
嘿,我懂你遇到的困扰了——直接让方块瞬间消失太生硬,想做渐隐但AnimationController的vsync参数总是报错对吧?别慌,我给你一套完整的解决方案,一步步来搞定:
核心问题解析
AnimationController 需要一个 TickerProvider 来同步动画与屏幕刷新节奏,通常我们会让页面的State类混入 SingleTickerProviderStateMixin(单动画场景下用这个足够),这样this就能作为合法的vsync参数。之前报错大概率是因为你没正确混入这个Mixin,或是在生命周期外初始化了控制器。
完整代码实现
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('渐隐方块示例')), body: const FadingBoxDemo(), ), ); } } class FadingBoxDemo extends StatefulWidget { const FadingBoxDemo({super.key}); @override State<FadingBoxDemo> createState() => _FadingBoxDemoState(); } // 关键:混入SingleTickerProviderStateMixin提供vsync能力 class _FadingBoxDemoState extends State<FadingBoxDemo> with SingleTickerProviderStateMixin { late AnimationController _fadeController; late Animation<double> _fadeAnimation; bool _isBoxVisible = false; @override void initState() { super.initState(); // 初始化动画控制器,时长设为3秒(可按需调整) _fadeController = AnimationController( duration: const Duration(seconds: 3), vsync: this, // 混入Mixin后,this就是合法的TickerProvider ); // 创建透明度动画:从完全可见(1.0)到完全透明(0.0) _fadeAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(_fadeController); // 监听动画状态,结束后隐藏方块并重置控制器 _fadeController.addStatusListener((status) { if (status == AnimationStatus.completed) { setState(() { _isBoxVisible = false; }); _fadeController.reset(); // 重置后可重复触发动画 } }); } @override void dispose() { // 页面销毁时释放控制器,避免内存泄漏 _fadeController.dispose(); super.dispose(); } void _triggerFade() { setState(() { _isBoxVisible = true; }); // 启动渐隐动画 _fadeController.forward(); } @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 红色触发按钮 ElevatedButton( style: ElevatedButton.styleFrom(backgroundColor: Colors.red), onPressed: _triggerFade, child: const Text('显示方块并渐隐'), ), const SizedBox(height: 20), // 带渐隐效果的方块 if (_isBoxVisible) AnimatedOpacity( opacity: _fadeAnimation.value, duration: _fadeController.duration!, child: Container( width: 150, height: 150, color: Colors.blue, ), ), ], ), ); } }
关键细节说明
- SingleTickerProviderStateMixin:这个Mixin给State类赋予了Ticker能力,确保动画和屏幕帧率完美同步,直接解决
vsync参数的报错问题。 - 动画状态监听:通过
addStatusListener捕获动画完成状态,结束后自动隐藏方块并重置控制器,保证下次点击按钮能正常触发新的动画。 - AnimatedOpacity:Flutter封装好的透明度动画组件,直接绑定动画值就能实现平滑过渡,比手动用
Opacity组件更省心。
如果不想用AnimatedOpacity,也可以直接用基础的Opacity组件:
Opacity( opacity: _fadeAnimation.value, child: Container( width: 150, height: 150, color: Colors.blue, ), )
这样就能实现方块在3秒内平滑渐隐消失的效果啦!
内容的提问来源于stack exchange,提问作者Ant D
相关产品推荐
相关产品推荐

