目錄
- 1. Flutter 中動畫的基本概念是什么?
- 2. 解釋 AnimationController 和 Tween 的作用
- 3. 如何實現一個補間(Tween)動畫?
- 4. 什么是隱式動畫?舉例說明
- 5. 如何實現自定義復雜動畫?
1. Flutter 中動畫的基本概念是什么?
在 Flutter 中,動畫是通過在一段時間內連續改變屬性值來實現的視覺效果變化。核心概念包括:
概念 | 說明 |
---|---|
動畫值 | 隨時間變化的數值(通常是 0.0 → 1.0) |
動畫控制器 | 管理動畫的播放、停止、反轉等操作 |
補間 (Tween) | 定義起始值和結束值之間的過渡(如位置、大小、顏色等) |
動畫曲線 | 控制動畫變化速率(如加速、減速、彈跳等) |
動畫監聽器 | 在動畫值變化時更新 UI |
動畫狀態 | 運行中 (forward)、完成 (completed)、反轉中 (reverse)、停止 (dismissed) |
動畫分類:
- 隱式動畫:自動處理的簡單動畫(如
AnimatedContainer
) - 顯式動畫:需要手動控制的復雜動畫(使用
AnimationController
)
2. 解釋 AnimationController 和 Tween 的作用
AnimationController
- 作用:管理動畫的播放狀態和持續時間
- 特點:
- 需要
TickerProvide*
(如SingleTickerProviderStateMixin
) - 默認輸出 0.0 → 1.0 的值
- 控制動畫播放 (
forward()
)、停止 (stop()
)、反轉 (reverse()
)
- 需要
- 創建:
late AnimationController _controller;
void initState() {super.initState();_controller = AnimationController(duration: const Duration(seconds: 2), // 動畫時長vsync: this, // 使用 TickerProvider);
}
Tween
- 作用:定義動畫的值范圍(如顏色、大小、位置等)
- 特點:
- 將 0.0→1.0 映射到實際值范圍
- 支持多種數據類型(
ColorTwee*
,SizeTween
等)
- 使用:
final Animation<double> _sizeAnim = Tween<double>(begin: 50.0, end: 200.0,
).animate(_controller);
3. 如何實現一個補間(Tween)動畫?
步驟:
- 創建
AnimationController
- 定義
Tween
并綁定控制器 - 添加監聽器重建 UI
- 啟動動畫
示例代碼:
class TweenAnimationDemo extends StatefulWidget { _TweenAnimationDemoState createState() => _TweenAnimationDemoState();
}class _TweenAnimationDemoState extends State<TweenAnimationDemo> with SingleTickerProviderStateMixin {late AnimationController _controller;late Animation<double> _sizeAnim;late Animation<Color?> _colorAnim;void initState() {super.initState();// 1. 創建控制器_controller = AnimationController(duration: const Duration(seconds: 2),vsync: this,)..repeat(reverse: true); // 循環播放// 2. 創建補間動畫_sizeAnim = Tween<double>(begin: 50, end: 200).animate(_controller);_colorAnim = ColorTween(begin: Colors.blue, end: Colors.red).animate(_controller);} Widget build(BuildContext context) {// 3. 使用 AnimatedBuilder 優化性能return AnimatedBuilder(animation: _controller,builder: (context, child) {return Center(child: Container(width: _sizeAnim.value,height: _sizeAnim.value,color: _colorAnim.value,),);},);}void dispose() {_controller.dispose(); // 釋放資源super.dispose();}
}
4. 什么是隱式動畫?舉例說明
隱式動畫:只需設置目標值,Flutter 自動處理動畫過程的簡化動畫。
特點:
- 無需管理
AnimationController
- 內置 300ms 默認動畫時長
- 通過
setState()
改變屬性值自動觸發
常用隱式動畫組件:
組件 | 作用 |
---|---|
AnimatedContainer | 容器屬性變化(大小/顏色等) |
AnimatedOpacity | 透明度變化 |
AnimatedPositioned | 位置變化(Stack 內) |
AnimatedAlign | 對齊方式變化 |
示例:點擊改變容器大小和顏色
class ImplicitAnimationDemo extends StatefulWidget { _ImplicitAnimationDemoState createState() => _ImplicitAnimationDemoState();
}class _ImplicitAnimationDemoState extends State<ImplicitAnimationDemo> {double _size = 100;Color _color = Colors.blue;void _animate() {setState(() {_size = _size == 100 ? 200 : 100;_color = _color == Colors.blue ? Colors.green : Colors.blue;});} Widget build(BuildContext context) {return GestureDetector(onTap: _animate,child: AnimatedContainer(duration: Duration(seconds: 1), // 動畫時長width: _size,height: _size,color: _color,curve: Curves.easeInOut, // 動畫曲線child: Center(child: Text('點擊我')),),);}
}
5. 如何實現自定義復雜動畫?
對于復雜動畫(如路徑動畫、物理動畫、多動畫同步),推薦使用:
1. 組合多個動畫
late Animation<double> _sizeAnim;
late Animation<double> _rotationAnim;
void initState() {super.initState();_sizeAnim = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(parent: _controller,curve: Interval(0.0, 0.5), // 只在前半段執行),);_rotationAnim = Tween(begin: 0.0, end: 2 * pi).animate(CurvedAnimation(parent: _controller,curve: Interval(0.5, 1.0), // 只在后半段執行),);
}
2. 使用物理動畫(SpringSimulation)
void _runSpringAnimation() {final spring = SpringSimulation(SpringDescription(mass: 1, stiffness: 100, damping: 10),0.0, // 起始位置300.0, // 目標位置10.0, // 初始速度);_controller.animateWith(spring);
}
3. 自定義動畫曲線
final customCurve = CurveTween(curve: Curves.easeInOutBack,
);_animation = customCurve.animate(_controller);
4. 使用動畫狀態機
_controller.addStatusListener((status) {if (status == AnimationStatus.completed) {_controller.reverse();} else if (status == AnimationStatus.dismissed) {_controller.forward();}
});
完整示例:彈跳球效果
class BouncingBallDemo extends StatefulWidget { _BouncingBallDemoState createState() => _BouncingBallDemoState();
}class _BouncingBallDemoState extends State<BouncingBallDemo>with SingleTickerProviderStateMixin {late AnimationController _controller;late Animation<double> _bounceAnim;void initState() {super.initState();_controller = AnimationController(duration: const Duration(seconds: 2),vsync: this,)..repeat(reverse: true);// 使用彈性曲線模擬彈跳_bounceAnim = Tween<double>(begin: 0, end: 300).animate(CurvedAnimation(parent: _controller,curve: Curves.elasticOut, // 彈性效果),);} Widget build(BuildContext context) {return AnimatedBuilder(animation: _controller,builder: (context, child) {return Stack(children: [Positioned(bottom: _bounceAnim.value,left: MediaQuery.of(context).size.width / 2 - 25,child: Container(width: 50,height: 50,decoration: BoxDecoration(color: Colors.red,shape: BoxShape.circle,),),),],);},);}
}