【Flutter 實戰】一文學會20多個動畫組件

 

 

老孟導讀:此篇文章是 Flutter 動畫系列文章第三篇,後續還有動畫序列、過分動畫、轉場動畫、自定義動畫等。html

 

Flutter 系統提供了20多個動畫組件,只要你把前面【動畫核心】(文末有連接)的文章看明白了,這些組件對你來講是很是輕鬆的,這些組件大部分都是對經常使用操做的封裝。git

顯示動畫組件

回顧上一篇【動畫核心】的文章中建立動畫三個必須的步驟:微信

  1. 建立 AnimationController。ide

  2. 監聽 AnimationController,調用 setState 刷新UI。學習

  3. 釋放 AnimationController。動畫

看第二步,每一個動畫都須要這個步驟,所以對其封裝,命名爲 MyAnimatedWidget:ui





class MyAnimatedWidget extends StatefulWidget { final AnimationController controller; final Widget child; const MyAnimatedWidget( {Key key, @required this.controller, @required this.child}) : super(key: key); @override _MyAnimatedWidgetState createState() => _MyAnimatedWidgetState();}class _MyAnimatedWidgetState extends State<MyAnimatedWidget> { @override void initState() { super.initState(); widget.controller.addListener(() { setState(() {}); }); } @override Widget build(BuildContext context) { return widget.child; }  @override void dispose() { super.dispose(); widget.controller.dispose(); }}

自定義的動畫組件只有兩個功能:this

  1. 監聽 AnimationController,調用 setStatespa

  2. 釋放 AnimationController。.net

而 AnimationController 的建立須要開發者自行建立,爲何封裝在自定義組件內?這個後面會介紹。

其實這個組件不用咱們本身封裝,由於系統已經封裝好了,在學習 Flutter 的過程當中自定義組件是很是重要的,所以多封裝一些組件,即便是系統已經存在的,用本身和系統的進行對比,能夠極大的提升咱們自定義組件的能力。

系統封裝的相似上面的組件是 AnimatedWidget,此類是抽象類,源代碼:

區別:

  1. 咱們使用 監聽 AnimationController,調用 setState ,而系統使用 Listenable,Listenable 是一個維護偵聽器列表的對象,用於通知客戶端該對象已被更新。

    Listenable 有兩個變體:

    AnimationController 的繼承結構:

    AnimationController 也是繼承自 Listenable,所以使用 Listenable 適用的範圍更廣,不只僅能夠用於 Animation ,還能夠用於 ChangeNotifier。

    1. ValueListenable :擴展[Listenable]接口的接口,具備當前值的概念。

    2. Animation:一個擴展[ValueListenable]接口的接口,添加方向(正向或反向)的概念。

  2. 因爲使用了 Listenable,所以監聽和釋放使用listenable.addListenerlistenable.removeListener

AnimatedWidget 是一個抽象類,不能直接使用,其子類包括:

ScaleTransition 爲例使用方式:








class AnimationDemo extends StatefulWidget { @override State<StatefulWidget> createState() => _AnimationDemo();}class _AnimationDemo extends State<AnimationDemo> with SingleTickerProviderStateMixin { AnimationController _animationController; Animation _animation; @override void initState() { _animationController = AnimationController(duration: Duration(seconds: 2), vsync: this); _animation = Tween(begin: .5, end: .1).animate(_animationController); //開始動畫 _animationController.forward(); super.initState(); } @override Widget build(BuildContext context) { return ScaleTransition( scale: _animation, child: Container( height: 200, width: 200, color: Colors.red, ), ); } @override void dispose() { _animationController.dispose(); super.dispose(); }}

和【動畫核心】中寫法惟一的不一樣是不須要主動調用 setState

AnimatedWidget 其餘子類的用法相似,不在一一介紹,其餘組件的詳細用法可到 http://laomengit.com/flutter/widgets/widgets_structure.html 中查看。

隱式動畫組件

AnimatedWidget 只是封裝了  setState,系統是否有封裝 AnimationController、Tween、Curve且自動管理AnimationController的組件呢?有的,此組件就是 ImplicitlyAnimatedWidget,ImplicitlyAnimatedWidget 也是一個抽象類,其子類包括:

AnimatedOpacity 爲例使用方式:



class AnimatedWidgetDemo extends StatefulWidget { @override _AnimatedWidgetDemoState createState() => _AnimatedWidgetDemoState();}class _AnimatedWidgetDemoState extends State<AnimatedWidgetDemo> { double _opacity = 1.0; @override Widget build(BuildContext context) { return Center( child: AnimatedOpacity( opacity: _opacity, duration: Duration(seconds: 2), child: GestureDetector( onTap: () { setState(() { _opacity = 0; }); }, child: Container( height: 60, width: 150, color: Colors.blue, ), ), ), ); }}

使用 AnimatedOpacity 咱們並無主動建立 AnimationController 和 Tween,是由於 AnimatedOpacity 內部已經建立了。

因此別看 Flutter 內置了20多種動畫組件,90% 都是對上面兩種方式的封裝,分別稱爲隱式動畫組件 和 顯示動畫組件:

  • 隱式動畫組件:只需提供給組件動畫開始、結束值,組件建立 AnimationController、Curve、Tween,執行動畫,釋放AnimationController,咱們稱之爲隱式動畫組件,隱式動畫組件有: AnimatedAlignAnimatedContainerAnimatedDefaultTextStyleAnimatedOpacityAnimatedPaddingAnimatedPhysicalModelAnimatedPositionedAnimatedPositionedDirectionalAnimatedThemeSliverAnimatedOpacityTweenAnimationBuilderAnimatedContainer 等。

  • 顯示動畫組件:須要設置 AnimationController,控制動畫的執行,使用顯式動畫能夠完成任何隱式動畫的效果,甚至功能更豐富一些,不過你須要管理該動畫的 AnimationController 生命週期,AnimationController 並非一個控件,因此須要將其放在 stateful 控件中。顯示動畫組件有: AlignTransitionAnimatedBuilderAnimatedModalBarrierDecoratedBoxTransitionDefaultTextStyleTransitionPositionedTransitionRelativePositionedTransitionRotationTransitionScaleTransitionSizeTransitionSlideTransitionFadeTransition 等。

不難看出,使用隱式動畫控件,代碼更簡單,並且無需管理 AnimationController 的生命週期,有人以爲隱式動畫組件多方便啊,爲何還要顯示動畫組件呢?由於:**封裝的越複雜,使用越簡單,每每伴隨着功能越不豐富。**好比想讓動畫一直重複執行,隱式動畫組件是沒法實現的。

顯示動畫組件和隱式動畫組件中各有一個萬能的組件,它們是 AnimatedBuilderTweenAnimationBuilder,當系統中不存在咱們想要的動畫組件時,可使用這兩個組件,以 AnimatedBuilder 爲例,實現 Container 大小和顏色同時動畫,







class AnimatedBuilderDemo extends StatefulWidget { @override _AnimatedBuilderDemoState createState() => _AnimatedBuilderDemoState();}class _AnimatedBuilderDemoState extends State<AnimatedBuilderDemo> with SingleTickerProviderStateMixin { AnimationController _controller; Animation<Color> _colorAnimation; Animation<Size> _sizeAnimation; @override void initState() { _controller = AnimationController(vsync: this, duration: Duration(seconds: 2)); _colorAnimation = ColorTween(begin: Colors.blue, end: Colors.red).animate(_controller); _sizeAnimation = SizeTween(begin: Size(100.0, 50.0), end: Size(200.0, 100.0)) .animate(_controller); _controller.forward(); super.initState(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Center( child: AnimatedBuilder( animation: _controller, builder: (context, widget) { return Container( width: _sizeAnimation.value.width, height: _sizeAnimation.value.height, color: _colorAnimation.value, ); }, ), ); }}

AnimatedBuilderTweenAnimationBuilder 本質上和其餘動畫組件沒有區別,只是給了咱們更高的靈活性。

如何選取

Flutter 內置的動畫組件分爲兩種:隱式動畫組件顯示動畫組件 ,顯示動畫組件只封裝了 setState 方法,須要開發者建立 AnimationController,並管理 AnimationController。隱式動畫組件封裝了 AnimationController、Curve、Tween,只需提供給組件動畫開始、結束值,其他由系統管理。

隱式動畫組件能夠完成效果,顯示動畫組件均可以完成,那麼何時使用隱式動畫組件?何時使用顯示動畫組件?

  1. 判斷你的動畫組件是否一直重複,好比一直轉圈的loading動畫,若是是選擇顯式動畫。

  2. 判斷你的動畫組件是否須要多個組件聯動,若是是選擇顯式動畫。

  3. 判斷你的動畫組件是否須要組合動畫,若是是選擇顯式動畫。

  4. 若是上面三個條件都是否,就選擇隱式動畫組件,判斷是否已經內置動畫組件,若是沒有,使用 TweenAnimationBuilder,有就直接使用內置動畫組件。

  5. 選擇顯式動畫組件,判斷是否已經內置動畫組件,若是沒有,使用 AnimatedBuilder,有就直接使用內置動畫組件。

邏輯圖以下:

還有一個簡單的區分辦法:若是你的動畫相對比較簡單,動畫從一種狀態過渡到另外一種狀態,不須要單獨控制 AnimationController,這種狀況下,隱式動畫組件通常能夠就能夠實現。

不過也沒有必要特別糾結使用隱式動畫組件仍是顯示動畫組件,無論使用哪種,實現效果便可。

 

 

你可能還喜歡

 

關注「老孟Flutter」

讓你天天進步一點點

 

本文分享自微信公衆號 - 老孟Flutter(lao_meng_qd)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索