動畫型別
動畫型別:
-
補間(Tween)動畫
“介於兩者之間”的簡稱。在補間動畫中,定義了開始點和結束點、時間線以及定義轉換時間和速度的曲線。然後由框架計算如何從開始點過渡到結束點。
-
基於物理的動畫
在基於物理的動畫中,運動被模擬為與真實世界的行為相似。例如,當你擲球時,它在何處落地,取決於拋球速度有多快、球有多重、距離地面有多遠。 類似地,將連線在彈簧上的球落下(並彈起)與連線到繩子上的球放下的方式也是不同。
動畫常見表現形式
- 動畫列表或網格
- 在網格或列表中新增或刪除元素時應用動畫
- 共享元素轉換(Hero)
- 實現路由(頁面)之間的共享元素過渡動畫
- 交錯動畫
- 交錯動畫由一個動畫序列或重疊的動畫組成
- 一個AnimationController控制所有動畫
動畫庫中的一些主要類
Animation
動畫系統的主要構件, 接收特定型別的值,該值可以在動畫的生命週期內更改。可以從該物件讀取動畫的當前值,並監聽該值的更改。
-
addListener(VoidCallback listener)
監聽Animation的值發生改變,如果要取動畫當前的值,呼叫animation.value即可
-
addStatusListener(AnimationStatusListener listener)
監聽動畫的狀態改變, AnimationStatus有四種狀態:dismissed、forward、reverse、completed
Animation<double> _animation = Tween(begin: 0.0, end: 350.0).animate(_animationController)
..addListener(() {
this.setState(() {});
})
..addStatusListener(
(AnimationStatus status) {
if (status == AnimationStatus.dismissed) {
}...
},
);
複製程式碼
AnimationController
建立一個動畫,離不開控制器AnimationController。
- 它會產生數值 0 -- 1 區間內的數值。
- 控制動畫 reverse(), forward(), animateTo(), stop() 等
- 繼承Animation<double>
- 切記路由銷燬時需要釋放動畫資源
AnimationController _animationController = AnimationController(
duration: Duration(milliseconds: _duration),
vsync: this,
);
複製程式碼
Tween
如上面的程式碼, Tween接收begin和end兩個引數,不僅可以是數值型別,也可以使用ColorTween, RectTween, BorderTween, AlignmentTween等接收Color, Rect, Border, Alignment等型別。
-
animate()
animate方法傳入Animation<double>,返回Animation<T>型別
-
繼承Animatable<T>
ColorTween _colorTween = ColorTween(
begin: Color(0xFFC1C1C1),
end: Color(0xFFC19426),
);
複製程式碼
Curves
動畫過程可以是勻速的、勻加速的或者先加速後減速等。通過Curve(曲線)來描述動畫過程,我們把勻速動畫稱為線性的(Curves.linear), 而非勻速動畫稱為非線性的。
AnimationController _controller = AnimationController(
duration: Duration(milliseconds: _duration),
vsync: this,
);
Animation _curvedAnimation = CurvedAnimation(
parent: _controller,
curve: Curves.easeIn,
);
Animation<int> alpha = IntTween(begin: 0, end: 255).animate(_curvedAnimation);
複製程式碼
Ticker
當建立AnimationController時, 需要傳遞一個vsync引數,它接收一個TickerProvider型別的物件,它的主要職責是建立Ticker.
通常我們使用State with SingleTickerProviderStateMixin,然後將State物件作為vsync的值。
class AnimationDialog extends StatefulWidget {
@override
AnimationDialogState createState() => AnimationDialogState();
}
class AnimationDialogState extends State<AnimationDialog>
with SingleTickerProviderStateMixin {
/// Animation Controller
AnimationController _animationController = AnimationController(
duration: Duration(milliseconds: 500),
vsync: this,
);
}
複製程式碼
AnimatedWidget
使用Animation的時候,一般使用addListener更新當前的State
animation.addListener(() {
setState(() {
//
});
});
複製程式碼
這就是AnimatedWidget的作用,AnimatedWidget繼承StatefulWidget,並接收Listenable物件,而Animation是繼承Listenable的。
使用方法:目標Widget繼承AnimatedWidget,接收AnimatedWidget引數。
class AnimatedLogo extends AnimatedWidget {
/// Animation
final Animation<double> animation;
AnimatedLogo({Key key, this.animation})
: super(key: key, listenable: animation);
Widget build(BuildContext context) {
return Center(
child: Container(
margin: EdgeInsets.symmetric(vertical: 10.0),
height: animation.value,
width: animation.value,
child: FlutterLogo(),
),
);
}
}
複製程式碼
AnimatedBuilder
在使用AnimatedWidget時,需要把目標Widget繼承AnimatedWidget,這樣寫多少有點麻煩。如果封裝一個Common類,接收animation物件和child,這就有了AnimatedWidget. Flutter中正是通過這樣的方式封裝了很多動畫,如:FadeTransition、ScaleTransition、SizeTransition、RotationTransition等,很多時候都可以複用這些過渡類。
class GrowTransition extends StatelessWidget {
GrowTransition({this.child, this.animation});
final Widget child;
final Animation<double> animation;
Widget build(BuildContext context) {
return new Center(
child: new AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) {
return new Container(
height: animation.value,
width: animation.value,
child: child
);
},
child: child
),
);
}
}
複製程式碼
Transform
Transform可以對子元件實現一些特效。
詳情請參考官方介紹: book.flutterchina.club/chapter5/tr…
Container(
color: Colors.black,
child: new Transform(
alignment: Alignment.topRight, //相對於座標系原點的對齊方式
transform: new Matrix4.skewY(0.3), //沿Y軸傾斜0.3弧度
child: new Container(
padding: const EdgeInsets.all(8.0),
color: Colors.deepOrange,
child: const Text('Apartment for rent!'),
),
),
);
複製程式碼
-
rotate
Transform.rotate可以對子元件進行旋轉變換。
-
scale
Transform.scale可以對子元件進行縮小或放大。
-
translate
Transform.translate接收一個offset引數,可以在繪製時沿x、y軸對子元件平移一定的距離。
動畫示例:
卡片彈出動畫對話方塊
實現方案:高度在持續變化的對話方塊
擴充套件:對話方塊可以從底部、上部、中間等位置出現。
主要程式碼:
Container(
height: _animation?.value ?? 0.0,
alignment: Alignment.bottomCenter,
child: SingleChildScrollView(
child: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_buildCardWidget(),
_buildBottomWidget(),
],
),
),
),
);
複製程式碼
參考網址:
動畫·《Flutter實戰》:book.flutterchina.club/chapter9/an…
以上程式碼地址:github.com/smiling1990…