## 交錯動畫
有些時候我們可能會需要一些復雜的動畫,這些動畫可能由一個動畫序列或重疊的動畫組成,比如:有一個柱狀圖,需要在高度增長的同時改變顏色,等到增長到最大高度后,我們需要在X軸上平移一段距離。這時我們就需要使用交錯動畫(Stagger Animation)。交錯動畫需要注意以下幾點:
1. 要創建交錯動畫,需要使用多個動畫對象
2. 一個AnimationController控制所有動畫
3. 給每一個動畫對象指定間隔(Interval)
所有動畫都由同一個[AnimationController](https://docs.flutter.io/flutter/animation/AnimationController-class.html)驅動,無論動畫實時持續多長時間,控制器的值必須介于0.0和1.0之間,而每個動畫的間隔(Interval)介于0.0和1.0之間。對于在間隔中設置動畫的每個屬性,請創建一個[Tween](https://docs.flutter.io/flutter/animation/Tween-class.html)。 Tween指定該屬性的開始值和結束值。也就是說0.0到1.0代表整個動畫過程,我們可以給不同動畫指定起始點和終止點來決定它們的開始時間和終止時間。
#### 示例
下面我們看一個例子,實現一個柱狀圖增長的動畫:
1. 開始時高度從0增長到300像素,同時顏色由綠色漸變為紅色;這個過程占據整個動畫時間的60%。
2. 高度增長到300后,開始沿X軸向右平移100像素;這個過程占用整個動畫時間的40%。
我們將執行動畫的Widget分離出來:
```
class StaggerAnimation extends StatelessWidget {
StaggerAnimation({ Key key, this.controller }): super(key: key){
//高度動畫
height = Tween<double>(
begin:.0 ,
end: 300.0,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.0, 0.6, //間隔,前60%的動畫時間
curve: Curves.ease,
),
),
);
color = ColorTween(
begin:Colors.green ,
end:Colors.red,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.0, 0.6,//間隔,前60%的動畫時間
curve: Curves.ease,
),
),
);
padding = Tween<EdgeInsets>(
begin:EdgeInsets.only(left: .0),
end:EdgeInsets.only(left: 100.0),
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.6, 1.0, //間隔,后40%的動畫時間
curve: Curves.ease,
),
),
);
}
final Animation<double> controller;
Animation<double> height;
Animation<EdgeInsets> padding;
Animation<Color> color;
Widget _buildAnimation(BuildContext context, Widget child) {
return Container(
alignment: Alignment.bottomCenter,
padding:padding.value ,
child: Container(
color: color.value,
width: 50.0,
height: height.value,
),
);
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
builder: _buildAnimation,
animation: controller,
);
}
}
```
StaggerAnimation中定義了三個動畫,分別是對Container的height、color、padding屬性設置的動畫,然后通過Interval來為每個動畫指定在整個動畫過程的起始點和終點。
下面我們來實現啟動動畫的路由:
```
class StaggerDemo extends StatefulWidget {
@override
_StaggerDemoState createState() => _StaggerDemoState();
}
class _StaggerDemoState extends State<StaggerDemo> with TickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 2000),
vsync: this
);
}
Future<Null> _playAnimation() async {
try {
//先正向執行動畫
await _controller.forward().orCancel;
//再反向執行動畫
await _controller.reverse().orCancel;
} on TickerCanceled {
// the animation got canceled, probably because we were disposed
}
}
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
_playAnimation();
},
child: Center(
child: Container(
width: 300.0,
height: 300.0,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.1),
border: Border.all(
color: Colors.black.withOpacity(0.5),
),
),
//調用我們定義的交錯動畫Widget
child: StaggerAnimation(
controller: _controller
),
),
),
);
}
}
```
執行效果如下,點擊灰色矩形,就可以看到整個動畫效果:

- 緣起
- 起步
- 移動開發技術簡介
- Flutter簡介
- 搭建Flutter開發環境
- 常見配置問題
- Dart語言簡介
- 第一個Flutter應用
- 計數器示例
- 路由管理
- 包管理
- 資源管理
- 調試Flutter APP
- Dart線程模型及異常捕獲
- 基礎Widgets
- Widget簡介
- 文本、字體樣式
- 按鈕
- 圖片和Icon
- 單選框和復選框
- 輸入框和表單
- 布局類Widgets
- 布局類Widgets簡介
- 線性布局Row、Column
- 彈性布局Flex
- 流式布局Wrap、Flow
- 層疊布局Stack、Positioned
- 容器類Widgets
- Padding
- 布局限制類容器ConstrainedBox、SizeBox
- 裝飾容器DecoratedBox
- 變換Transform
- Container容器
- Scaffold、TabBar、底部導航
- 可滾動Widgets
- 可滾動Widgets簡介
- SingleChildScrollView
- ListView
- GridView
- CustomScrollView
- 滾動監聽及控制ScrollController
- 功能型Widgets
- 導航返回攔截-WillPopScope
- 數據共享-InheritedWidget
- 主題-Theme
- 事件處理與通知
- 原始指針事件處理
- 手勢識別
- 全局事件總線
- 通知Notification
- 動畫
- Flutter動畫簡介
- 動畫結構
- 自定義路由過渡動畫
- Hero動畫
- 交錯動畫
- 自定義Widget
- 自定義Widget方法簡介
- 通過組合現有Widget實現
- 實例:TurnBox
- CustomPaint與Canvas
- 實例:圓形漸變進度條(自繪)
- 文件操作與網絡請求
- 文件操作
- Http請求-HttpClient
- Http請求-Dio package
- 實例:Http分塊下載
- WebSocket
- 使用Socket API
- Json轉Model
- 包與插件
- 開發package
- 插件開發:平臺通道簡介
- 插件開發:實現Android端API
- 插件開發:實現IOS端API
- 系統能力調用
- 國際化
- 讓App支持多語言
- 實現Localizations
- 使用Intl包
- Flutter核心原理
- Flutter UI系統
- Element和BuildContext
- RenderObject與RenderBox
- Flutter從啟動到顯示