交錯動畫
- 交錯動畫由序列或重疊的動畫組成苞氮。
- 要創(chuàng)建交錯動畫,使用多個動畫對象。
- 一個AnimationController控制所有動畫。
- 每個動畫對象在間隔期間指定動畫椒舵。
- 對于要設(shè)置動畫的每個屬性,請創(chuàng)建一個Tween约谈。
Terminology: 如果補間或補間的概念對您來說是新的笔宿,請參閱Flutter教程中的動畫
交錯的動畫是一個直截了當?shù)母拍睿阂曈X變化發(fā)生在一系列操作中,而不是一次性發(fā)生窗宇。 動畫可能是純粹順序的措伐,在下一個動畫之后會發(fā)生一次更改特纤,或者可能部分或完全重疊军俊。 它也可能有間隙,沒有發(fā)生變化捧存。
本指南介紹了如何在Flutter中構(gòu)建交錯動畫粪躬。
Examples
本指南介紹了basic_staggered_animation示例。您還可以參考更復雜的示例staggered_pic_selection昔穴。
basic_staggered_animation
顯示單個窗口小部件的一系列連續(xù)和重疊動畫镰官。 點擊屏幕會開始一個動畫届吁,可以改變不透明度眷细,大小,形狀礼搁,顏色和填充宙搬。
顯示從以三種尺寸之一顯示的圖像列表中刪除圖像笨腥。此示例使用兩個動畫控制器: 一個用于圖像選擇/取消選擇,另一個用于圖像刪除勇垛。 選擇/取消選擇動畫是錯開的脖母。 (要查看此效果,您可能需要增加timeDilation
值闲孤。) 選擇一個最大的圖像谆级,它會縮小,因為它在藍色圓圈內(nèi)顯示一個復選標記讼积。 接下來肥照,選擇一個最小的圖像,當復選標記消失時勤众,大圖像會擴展舆绎。 在大圖像完成展開之前,小圖像會縮小以顯示其復選標記决摧。 這種交錯行為類似于您在Google相冊中看到的行為亿蒸。
以下視頻演示了basic_staggered_animation執(zhí)行的動畫:
在視頻中凑兰,您會看到單個小部件的以下動畫,該小部件以帶有略微圓角的邊框藍色方塊開始边锁。 該方塊按以下順序運行更改:
- 淡入
- 擴大
- 向上移動時變得更高
- 轉(zhuǎn)變?yōu)橛羞吔绲膱A圈
- 將顏色更改為橙??色
向前跑之后姑食,動畫反向運行。
Flutter新手?
本頁假定您知道如何使用Flutter的小部件創(chuàng)建布局茅坛。 有關(guān)更多信息音半,請參閱在Flutter中構(gòu)建布局.
交錯動畫的基本結(jié)構(gòu)
- 所有動畫都由同一個AnimationController驅(qū)動贡蓖。
- 無論動畫實時持續(xù)多長時間曹鸠,控制器的值必須介于0.0和1.0之間。
- 每個動畫的間隔介于0.0和1.0之間斥铺。
- 對于在間隔中設(shè)置動畫的每個屬性彻桃,請創(chuàng)建一個Tween。 Tween指定該屬性的開始值和結(jié)束值晾蜘。
- Tween生成一個由控制器管理的Animation對象邻眷。
下圖顯示了basic_staggered_animation示例中使用的間隔。 您可能會注意到以下特征:
- 不透明度在時間軸的前10%期間發(fā)生變化剔交。
- 不透明度的變化與寬度的變化之間存在微小的差距肆饶。
- 在最后25%的時間線中沒有任何動畫。
- 增加填充使小部件看起來向上岖常。
- 將邊框半徑增加到0.5驯镊,將帶圓角的方形轉(zhuǎn)換為圓形。
- 填充和邊界半徑變化發(fā)生在相同的精確間隔期間竭鞍,但它們不必板惑。
要設(shè)置動畫:
- 創(chuàng)建一個管理所有動畫的AnimationController。
- 為每個動畫屬性創(chuàng)建一個Tween笼蛛。
- Tween定義了一系列值洒放。
- Tween的
animate
方法需要parent
控制器,并為該屬性生成一個Animation滨砍。
- 在動畫
curve
屬性上指定間隔往湿。
當控制動畫的值更改時,新動畫的值會更改惋戏,從而觸發(fā)UI更新领追。
以下代碼為width
屬性創(chuàng)建補間。 它構(gòu)建一個CurvedAnimation 响逢,指定一個緩和的曲線绒窑。 有關(guān)其他可用的預定義動畫曲線,請參閱曲線舔亭。
width = Tween<double>(
begin: 50.0,
end: 150.0,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.125, 0.250,
curve: Curves.ease,
),
),
),
begin
和 end
的值不必是雙倍的些膨。下面的代碼使用BorderRadius.circular()
為borderRadius
屬性(控制方塊角的圓度)構(gòu)建補間蟀俊。
borderRadius = BorderRadiusTween(
begin: BorderRadius.circular(4.0),
end: BorderRadius.circular(75.0),
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.375, 0.500,
curve: Curves.ease,
),
),
),
完成交錯的動畫
與所有交互式小部件一樣,完整的動畫由小部件對組成:無狀態(tài)小部件和有狀態(tài)小部件订雾。
無狀態(tài)窗口小部件指定補間肢预,定義Animation對象,并提供build()
函數(shù)洼哎,負責構(gòu)建窗口小部件樹的動畫部分烫映。
有狀態(tài)小部件創(chuàng)建控制器,播放動畫噩峦,并構(gòu)建小部件樹的非動畫部分锭沟。 在屏幕中的任何位置檢測到點擊時,動畫開始识补。
basic_staggered_animation’s main.dart的完整代碼
無狀態(tài)小部件:StaggerAnimation
在無狀態(tài)小部件StaggerAnimation中族淮, build()
函數(shù)實例化一個AnimatedBuilder - 一個用于構(gòu)建動畫的通用小部件。 AnimatedBuilder構(gòu)建一個小部件并使用Tweens的當前值配置它李请。 該示例創(chuàng)建一個名為_buildAnimation()
的函數(shù)(執(zhí)行實際的UI更新)瞧筛,并將其分配給其builder
屬性。 AnimatedBuilder監(jiān)聽來自動畫控制器的通知导盅,在值發(fā)生變化時將小部件樹標記為臟。 對于動畫的每個刻度揍瑟,值都會更新白翻,從而調(diào)用_buildAnimation()
。
class StaggerAnimation extends StatelessWidget {
StaggerAnimation({ Key key, this.controller }) :
// Each animation defined here transforms its value during the subset
// of the controller's duration defined by the animation's interval.
// For example the opacity animation transforms its value during
// the first 10% of the controller's duration.
opacity = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.0, 0.100,
curve: Curves.ease,
),
),
),
// ... Other tween definitions ...
super(key: key);
final Animation<double> controller;
final Animation<double> opacity;
final Animation<double> width;
final Animation<double> height;
final Animation<EdgeInsets> padding;
final Animation<BorderRadius> borderRadius;
final Animation<Color> color;
// This function is called each time the controller "ticks" a new frame.
// When it runs, all of the animation's values will have been
// updated to reflect the controller's current value.
Widget _buildAnimation(BuildContext context, Widget child) {
return Container(
padding: padding.value,
alignment: Alignment.bottomCenter,
child: Opacity(
opacity: opacity.value,
child: Container(
width: width.value,
height: height.value,
decoration: BoxDecoration(
color: color.value,
border: Border.all(
color: Colors.indigo[300],
width: 3.0,
),
borderRadius: borderRadius.value,
),
),
),
);
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
builder: _buildAnimation,
animation: controller,
);
}
}
有狀態(tài)小部件:StaggerDemo
有狀態(tài)小部件StaggerDemo創(chuàng)建了AnimationController(規(guī)定他們的對象)绢片,指定持續(xù)時間為2000毫秒滤馍。 它播放動畫,并構(gòu)建小部件樹的非動畫部分底循。 在屏幕中檢測到點擊時動畫開始巢株。 動畫向前,然后向后熙涤。
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
);
}
// ...Boilerplate...
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) {
timeDilation = 10.0; // 1.0 is normal animation speed.
return Scaffold(
appBar: AppBar(
title: const Text('Staggered Animation'),
),
body: 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),
),
),
child: StaggerAnimation(
controller: _controller.view
),
),
),
),
);
}
}
資源
編寫動畫時阁苞,以下資源可能會有所幫助:
列出Flutter動畫的可用文檔。 如果補間對您來說不熟悉祠挫,請查看動畫教程 那槽。
所有Flutter庫的參考文檔。 特別是等舔,請參閱動畫庫文檔骚灸。
演示應用程序展示了許多材料組件和其他Flutter功能。 Shrine demo實現(xiàn)了英雄動畫慌植。
描述材料應用的動作甚牲。