Flutter 组件介绍:TickerMode
Flutter 组件介绍:TickerMode
在 Flutter 动画系统中,经常会遇到一个需求:当某个页面或组件不可见时,是否还需要继续执行动画?
为了高效利用性能,Flutter 提供了一个小而强大的组件 —— TickerMode
。
什么是 Ticker?
在介绍 TickerMode
之前,先简单回顾一下 Ticker 的概念。
Ticker
是 Flutter 动画的心跳信号,通常由AnimationController
管理。- 它会在每一帧(通常是 60fps)回调,驱动动画值的变化。
- 但如果页面不可见、动画仍然在执行,就会造成 性能浪费。
这时候,TickerMode
就派上用场了。
TickerMode
简介
TickerMode
是一个 InheritedWidget,用于 开启或关闭子树中所有 Ticker 的动画驱动。
它的主要参数是:
const TickerMode({Key? key,required bool enabled,required Widget child,
})
- enabled:是否启用 Ticker。
- true → 子树中的动画照常运行。
- false → 子树中的动画暂停。
- child:受控的子组件树。
使用场景
1. Tab 页切换
在多个 Tab 页中,每个页面可能有动画。如果用户切换到另一个 Tab,当前页面的动画其实不需要继续运行。
→ 使用 TickerMode(enabled: false) 可以暂停不可见页面的动画。
2. 底部导航切换
类似场景,当切换页面时,只有当前页面需要执行动画。
3. 节省性能
对于 长列表 / 复杂动画场景,可以有效减少不必要的 GPU / CPU 消耗。
示例代码
基础用法
import 'package:flutter/material.dart';class TickerModeDemo extends StatefulWidget { _TickerModeDemoState createState() => _TickerModeDemoState();
}class _TickerModeDemoState extends State<TickerModeDemo>with SingleTickerProviderStateMixin {late AnimationController _controller;bool _isEnabled = true;void initState() {super.initState();_controller = AnimationController(duration: const Duration(seconds: 2),vsync: this,)..repeat(reverse: true);}void dispose() {_controller.dispose();super.dispose();} Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("TickerMode 示例")),body: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// 使用 TickerMode 控制动画是否执行TickerMode(enabled: _isEnabled,child: FadeTransition(opacity: _controller,child: const Icon(Icons.favorite, size: 100, color: Colors.red),),),const SizedBox(height: 20),ElevatedButton(onPressed: () {setState(() {_isEnabled = !_isEnabled;});},child: Text(_isEnabled ? "暂停动画" : "启动动画"),),],),);}
}
效果:
• 点击按钮可以切换 动画启用 / 暂停。
• 当 enabled: false 时,动画会静止在当前帧,不再更新。
Tab 示例:配合 IndexedStackclass TickerTabDemo extends StatefulWidget { _TickerTabDemoState createState() => _TickerTabDemoState();
}class _TickerTabDemoState extends State<TickerTabDemo>with SingleTickerProviderStateMixin {int _currentIndex = 0;late AnimationController _controller;void initState() {super.initState();_controller =AnimationController(vsync: this, duration: const Duration(seconds: 2))..repeat(reverse: true);}void dispose() {_controller.dispose();super.dispose();}Widget _buildPage(int index) {return Center(child: TickerMode(enabled: _currentIndex == index,child: FadeTransition(opacity: _controller,child: Icon(Icons.star, size: 100, color: Colors.blue[index * 100]),),),);} Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("Tab + TickerMode 示例")),body: IndexedStack(index: _currentIndex,children: List.generate(3, (index) => _buildPage(index)),),bottomNavigationBar: BottomNavigationBar(currentIndex: _currentIndex,onTap: (i) => setState(() => _currentIndex = i),items: const [BottomNavigationBarItem(icon: Icon(Icons.star), label: "Tab1"),BottomNavigationBarItem(icon: Icon(Icons.star), label: "Tab2"),BottomNavigationBarItem(icon: Icon(Icons.star), label: "Tab3"),],),);}
}
效果:
• 只有当前 Tab 页的动画会继续执行。
• 切换到其他 Tab 时,对应的动画会自动暂停。
注意事项
1. TickerMode 不会销毁 动画控制器,只是暂停 Ticker 的心跳。
2. 动画暂停时,会停留在当前的帧位置,不会回到初始状态。
3. 如果页面切换时需要彻底释放资源,还是需要 dispose() 掉 AnimationController。
4. TickerMode 主要用于 临时禁用动画,而不是管理生命周期。
总结
• Ticker:动画的心跳驱动器。
• TickerMode:统一开关子树中所有 Ticker 的驱动。
• 主要作用:
• 节省性能
• 避免不可见页面仍然执行动画
• 常用于 TabView、IndexedStack、BottomNavigationBar 等多页面场景
通过 TickerMode,我们可以让 Flutter 动画在 性能优化 和 用户体验 之间取得更好的平衡。 🚀