Flutter 內建動畫
上面的那些一般用起來不是很方便,即便是 AnimatedBuilder 還是要指定參與動畫變化的 widget 屬性,為了進一步方便我們,官方在 AnimatedWidget
的基礎上封裝了下面這些內建動畫庫,就是 android 中的那些,當然更多一些:
SlideTransition
- 自身倍數位移動畫AlignTransition
- 沒找到資料PositionedTransition
- 縮放動畫,限定父佈局只能是 stackFadeTransition
- 透明度動畫ScaleTransition
- 縮放動畫,這個是 android 中的那種縮放動畫,可以指定中心點SizeTransition
- 寬高動畫,限制是每次只能執行一個維度的動畫,寬和高一起不行,那就是縮放動畫了RotationTransition
- 旋轉動畫,特點是其數值是 0-1 之間的,旋轉90度 = 0.25
這些 transition 的特點就是,用一個引數接受 animation 動畫,child 寫 widget
FadeTransition
FadeTransition
是透明度動畫,引數就是一個 opacity 指定動畫,child 寫 widget 就沒了
animationController = AnimationController(
duration: Duration(milliseconds: 300),
vsync: this,
);
animation = CurvedAnimation(parent: animationController, curve: Curves.bounceInOut);
animation = Tween(begin: 0.0, end: 1.0).animate(animationController);
複製程式碼
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FadeTransition(
opacity: animation,
child: Container(
margin: EdgeInsets.only(bottom: 20),
width: 300,
height: 300,
color: Colors.blueAccent,
),
),
RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
],
),
);
}
}
複製程式碼
SlideTransition
SlideTransition
位移動畫,使用 offset
來承載x,y軸資料。需要注意的是 Offset(0.0, 0.0)
中的數值都是 倍數
,也就是說 SlideTransition
只支援按 widget 本身長寬的倍數位移,不支援具體的數值的位移操作
void initState() {
super.initState();
animationController = AnimationController(
duration: Duration(milliseconds: 300),
vsync: this,
);
animation = Tween(begin: Offset(0.0, 0.0), end: Offset(1.0, 1.0))
.animate(animationController);
}
複製程式碼
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SlideTransition(
position: animation,
child: Container(
margin: EdgeInsets.only(bottom: 20),
width: 100,
height: 100,
color: Colors.blueAccent,
),
),
RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
],
),
);
}
複製程式碼
PositionedTransition
PositionedTransition
縮放動畫,必須在 stack
中使用,其縮放數值使用 RelativeRect
包裹,前後變化的是距 stack
父佈局左上右下4個角的距離:
animation = RelativeRectTween(
begin: RelativeRect.fromLTRB(0, 0, 0, 0),
end: RelativeRect.fromLTRB(50, 200, 50, 200))
.animate(animationController);
複製程式碼
大家看個圖:
基本上就是這個思路了,限制有一些,下面是例子程式碼,不是上面 gif 的程式碼:
Animation<RelativeRect> animation;
AnimationController animationController;
CurvedAnimation curve;
void initState() {
super.initState();
animationController = AnimationController(
duration: Duration(milliseconds: 300),
vsync: this,
);
curve = CurvedAnimation(parent: animationController, curve: Curves.bounceInOut);
animation = RelativeRectTween(
begin: RelativeRect.fromLTRB(0, 0, 0, 0),
end: RelativeRect.fromLTRB(50, 200, 50, 200))
.animate(curve);
}
複製程式碼
Widget build(BuildContext context) {
return Center(
child: Stack(
children: <Widget>[
PositionedTransition(
rect: animation,
child: Container(
width: 300,
height: 300,
color: Colors.blueAccent,
),
),
Positioned(
top: 20,
left: 20,
child: RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
),
],
),
);
}
複製程式碼
最後大家注意啊,RelativeRectTween begin 的數值能影響 widget 初始顯示時的寬高大小
ScaleTransition
ScaleTransition
這才是傳統的縮放動畫,使用 alignment: Alignment.topLeft
指定縮放中心點
Animation<double> animation;
AnimationController animationController;
CurvedAnimation curve;
@override
void initState() {
super.initState();
animationController = AnimationController(
duration: Duration(milliseconds: 300),
vsync: this,
);
curve =
CurvedAnimation(parent: animationController, curve: Curves.bounceInOut);
animation = Tween(
begin: 1.0,
end: 0.3,
).animate(curve);
}
複製程式碼
Widget build(BuildContext context) {
return Center(
child: Stack(
children: <Widget>[
ScaleTransition(
alignment: Alignment.topLeft,
scale: animation,
child: Container(
width: 300,
height: 300,
color: Colors.blueAccent,
),
),
Positioned(
top: 20,
left: 20,
child: RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
),
],
),
);
}
複製程式碼
SizeTransition
SizeTransition
寬高動畫,限制是每次只能設定一個維度,不能寬和高一起,優點是寬高的變化不會引起內容的變形
axis: Axis.horizontal
就是指定動畫作用與寬還是高
Widget build(BuildContext context) {
return Center(
child: Stack(
children: <Widget>[
SizeTransition(
axis: Axis.horizontal,
sizeFactor: animation,
child: Container(
color: Colors.blueAccent,
child: Icon(Icons.access_alarm, size: 300),
),
),
Positioned(
top: 20,
left: 20,
child: RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
),
],
),
);
}
複製程式碼
RotationTransition
RotationTransition
旋轉動畫,特點是其數值是 0-1 之間的,旋轉90度 = 0.25,依然可以設定原點
animation = Tween(
begin: 0.0,
end: 0.25,
).animate(curve);
複製程式碼
Widget build(BuildContext context) {
return Center(
child: Stack(
children: <Widget>[
RotationTransition(
turns: animation,
alignment: Alignment.center,
child: Container(
color: Colors.blueAccent,
child: Icon(Icons.access_alarm, size: 300),
),
),
Positioned(
top: 20,
left: 20,
child: RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
),
],
),
);
}
複製程式碼