【Flutter 元件集錄】AnimatedOpacity| 8月更文挑戰

張風捷特烈發表於2021-08-09
前言:

這是我參與8月更文挑戰的第 9 天,活動詳情檢視:8月更文挑戰。為應掘金的八月更文挑戰,我準備在本月挑選 31 個以前沒有介紹過的元件,進行全面分析和屬性介紹。這些文章將來會作為 Flutter 元件集錄 的重要素材。希望可以堅持下去,你的支援將是我最大的動力~

本系列元件文章列表
1.NotificationListener2.Dismissible3.Switch
4.Scrollbar5.ClipPath6.CupertinoActivityIndicator
7.Opacity8.FadeTransition9. AnimatedOpacity [本文]

一、認識 AnimatedOpacity 元件

上兩篇介紹了 Opacity 元件 和 FadeTransition 元件,他們都和操作元件的透明度有關。除了這兩位,還有一個元件也和透明度有關,它就是: AnimatedOpacity。和 FadeTransition 元件的功能是一樣的,它也可以進行 透明度漸變動畫。那他和 FadeTransition 有什麼異同點,為什麼框架中會給出兩個功能一致的元件?帶著這個問題,我們來開始認識 AnimatedOpacity 元件。


1.AnimatedOpacity 基本資訊

我們通過繼承樹可以看出,該元件繼承自 ImplicitlyAnimatedWidget ,是一個 StatefulWidgetImplicitlyAnimatedWidget 稱之為 隱式動畫,其最大的特點是: 使用者無需自己提供 動畫器,也可以進行動畫變換。


通過 AnimatedOpacity 的構造入參,可以發現,它確實不需要傳入動畫器,但可以指定動畫相關的 時長動畫曲線。從這裡,很容易猜出 ImplicitlyAnimatedWidget 相關類會維護 動畫控制器,封裝動畫的操作。這樣的目的很清楚:避免使用者直接和 動畫器 打交道,方便使用。從這裡可以衍生出一個問題 : 既然使用者無法直接操縱動畫器,那麼動畫是如何被開啟的? 帶著問題,繼續往下看。


2.AnimatedOpacity 的使用

我們先來看一個 AnimatedOpacity 使用的小 demo 。如下,通過 Switch 來切換 AnimatedOpacityopacity 的值。可見,當 opacity 配置屬性變化時,就會執行動畫。

下面程式碼中,通過 Wrap 元件,豎直包裹 SwitchContainer ,其中容器裡放著 AnimatedOpacity,讓一個圖示進行動畫變化。在 Switch 點選時,重新構建 AnimatedOpacity 並更新 opacity 的配置值。然後就神奇地執行動畫了,可以看出,動畫的執行和元件重構是有關係的。

class AnimatedOpacityDemo extends StatefulWidget {
  @override
  _AnimatedOpacityDemoState createState() => _AnimatedOpacityDemoState();
}

class _AnimatedOpacityDemoState extends State<AnimatedOpacityDemo> {
  final double beginOpacity = 1.0;
  final double endOpacity = 0;

  late double _opacity;

  @override
  void initState() {
    super.initState();
    _opacity = beginOpacity;
  }

  bool get selected => _opacity == 0;

  @override
  Widget build(BuildContext context) {
    return Wrap(
      direction: Axis.vertical,
      crossAxisAlignment: WrapCrossAlignment.center,
      children: <Widget>[
        Switch(
          value: selected,
          onChanged: onChanged,
        ),
        Container(
          color: Colors.grey.withAlpha(22),
          width: 100,
          height: 100,
          child: buildAnimatedOpacity(),
        ),
      ],
    );
  }

  Widget buildAnimatedOpacity() =>
      AnimatedOpacity(
        duration: const Duration(seconds: 1),
        curve: Curves.fastOutSlowIn,
        opacity: _opacity,
        child: _buildChild(),
      );

  void onChanged(bool value) {
    setState(() {
      _opacity = value ? endOpacity : beginOpacity;
    });
  }

  Widget _buildChild() =>
      const Icon( Icons.add_to_drive, color: Colors.green, size: 60 );
}
複製程式碼

3.AnimatedOpacity 的價值

AnimatedOpacity 元件最大的亮點在於只要其 opacity 屬性發生變化,並重新構建,就可以進行動畫。下面的案例更能體現它的價值:通過 Slider 的滑動,控制 AnimatedOpacityopacity 屬性變化,及重新構建。這樣每當滑動到新的值,都會 動畫漸變到該透明度,如果使用 FadeTransition 元件,自己操作縱動畫器來實現,就會比較複雜。 AnimatedOpacity 元件這類的隱式動畫大大降低了使用者使用動畫的門檻

// Slider 元件構建
Container(
  height: 50,
  child: Slider(
    label: "$_opacity",
    value: _opacity,
    divisions: 5,
    onChanged: onChanged,
  ),
),

void onChanged(double value) {
  setState(() {
    _opacity = value;
  });
}
複製程式碼

另外,AnimatedOpacity 可以通過 onEnd 回撥監聽動畫執行完畢的時機。


三、 AnimatedOpacity 的原始碼實現

1. AnimatedOpacity 原始碼分析

前面說過 AnimatedOpacity 繼承自 ImplicitlyAnimatedWidget

ImplicitlyAnimatedWidget 最為 StatefulWidget 需要實現 createState 建立 State 物件,但由於其是抽象類,可以選擇不實現,交由子類完成。

ImplicitlyAnimatedWidget 中沒有實現 createState ,而把返回的狀態型別將限制為 ImplicitlyAnimatedWidgetState<ImplicitlyAnimatedWidget>


AnimatedOpacity 作為 ImplicitlyAnimatedWidget 子類,需要實現 createState 抽象方法。如下,狀態類為 _AnimatedOpacityState

這樣元件層面的原始碼就理清了,ImplicitlyAnimatedWidget 相當於一箇中間層,可以通過 ImplicitlyAnimatedWidgetState 額外做一些事情。其子類元件的建立的狀態類,也需要繼承自 ImplicitlyAnimatedWidgetState 。下面就來看看,狀態類做了什麼。


2. 狀態類的處理

實現來看作為實現類的 _AnimatedOpacityState 。非常簡單,就是維護 _opacityAnimation,依賴於 FadeTransition 元件進行動畫。是不是想直呼 好傢伙


動畫控制器的源泉在於抽象的狀態類 ImplicitlyAnimatedWidgetState ,這裡將進行 動畫控制器 的監聽、開啟等維護工作。

initState 中會對動畫器進行監聽,如果動畫完成,會執行 onEnd 回撥。


3. 動畫的開啟

看到這裡,你應該能猜出來動畫觸發的時機。當 StatefulWidget重新構建時,狀態類是不會重新初始化的。而是觸發 State#didUpdateWidget 來通知 Widget 配置的變更,在此可以處理一下元件更新的邏輯。可以看出,在 ImplicitlyAnimatedWidgetState#didUpdateWidget 中,會對配置進行對比,發生變化將會更新。最後 _controller 會執行 forward 進行動畫。


AnimatedOpacity 元件,本質上就是對 動畫控制器FadeTransition 元件的一層封裝。簡化使用者對動畫使用的門檻,降低動畫使用的錯誤率。其他的隱式動畫元件也是類似,AnimatedOpacity 的使用方式到這裡就介紹完畢,那本文到這裡就結束了,謝謝觀看,明天見~

相關文章