Flutter | 求求你們了,切換 Widget 的時候加上動畫吧

Flutter筆記發表於2019-07-26

平時我們在切換 Widget 的時候是怎樣的呢?

有沒有動畫效果?是不是直接改變了一個 Widget?

類似於這樣的:

Flutter | 求求你們了,切換 Widget 的時候加上動畫吧

如果是的話,那麼今天所說的 Widget,絕對符合你的口味。

那如何在 Flutter 當中切換 Widget 的時候加上特效?完成這樣的效果?

Flutter | 求求你們了,切換 Widget 的時候加上動畫吧

AnimatedSwitcher 瞭解一下。

AnimatedSwitcher

官方介紹

話不多說,功能我們已經瞭解,再來看一下官方的介紹:

A widget that by default does a FadeTransition between a new widget and the widget previously set on the AnimatedSwitcher as a child.

If they are swapped fast enough (i.e. before duration elapses), more than one previous child can exist and be transitioning out while the newest one is transitioning in.

If the "new" child is the same widget type and key as the "old" child, but with different parameters, then AnimatedSwitcher will not do a transition between them, since as far as the framework is concerned, they are the same widget and the existing widget can be updated with the new parameters. To force the transition to occur, set a Key on each child widget that you wish to be considered unique (typically a ValueKey on the widget data that distinguishes this child from the others).

大致意思就是:

預設情況下是執行透明度的動畫。

如果交換速度足夠快,則存在多個子級,但是在新子級傳入的時候將它移除。

如果新 Widget 和 舊 Widget 的型別和鍵相同,但是引數不同,那麼也不會進行轉換。如果想要進行轉換,那麼要新增一個 Key。

建構函式

再來看建構函式,來確定如何使用:

const AnimatedSwitcher({
  Key key,
  this.child,
  @required this.duration,
  this.reverseDuration,
  this.switchInCurve = Curves.linear,
  this.switchOutCurve = Curves.linear,
  this.transitionBuilder = AnimatedSwitcher.defaultTransitionBuilder,
  this.layoutBuilder = AnimatedSwitcher.defaultLayoutBuilder,
}) : assert(duration != null),
assert(switchInCurve != null),
assert(switchOutCurve != null),
assert(transitionBuilder != null),
assert(layoutBuilder != null),
super(key: key);
複製程式碼

來解釋一下每個引數:

  1. child:不用多說
  2. duration:動畫持續時間
  3. reverseDuration:從新的 Widget 到舊的 Widget 動畫持續時間,如果不設定則為 duration 的值
  4. switchInCurve:動畫效果
  5. switchOutCurve:同上
  6. transitionBuilder:設定一個新的轉換動畫
  7. layoutBuilder:包裝新舊 Widget 的元件,預設是一個 Stack

其中必要引數就是一個 duration,那既然知道如何使用了,那就開擼。

簡單例子

前面我們看的圖,就是在對 AppBar上的 actions 進行操作,

其實這個例子在實際開發當中經常存在,肯定要刪除一些東西的嘛,然後選中了以後批量刪除。

那這裡也不多說,直接上程式碼,然後解釋:

class _AnimatedSwitcherPageState extends State<AnimatedSwitcherPage> {
  IconData _actionIcon = Icons.delete;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('AnimatedSwitcherPage'),
          actions: <Widget>[
            AnimatedSwitcher(
              transitionBuilder: (child, anim){
                return ScaleTransition(child: child,scale: anim);
              },
              duration: Duration(milliseconds: 300),
              child: IconButton(
                  key: ValueKey(_actionIcon),
                  icon: Icon(_actionIcon),
                  onPressed: () {
                    setState(() {
                      if (_actionIcon == Icons.delete)
                        _actionIcon = Icons.done;
                      else
                        _actionIcon = Icons.delete;
                    });
                  }),
            )
          ],
        ),
        body: Container());
  }
}
複製程式碼

我們定義的是一個 StatefulWidget,因為在切換 Widget 的時候要呼叫 setState()

下面來說一下整個流程:

  1. 首先定義好我們初始化的 Icon的資料為 Icons.delete
  2. AppBaractions 裡面加入 AnimatedSwitcher
  3. 設定 transitionBuilder 為 縮放動畫 ScaleTransition
  4. AnimatedSwitcher 的 child 為 IconButton
  5. 因為前面官方文件說過,如果 Widget 型別一樣,只是資料不一樣,那麼想要動畫,就必須新增 Key。
  6. 所以我們給 IconButton 新增了一個 ValueKey,值就為定義好的 IconData
  7. 最後在點選事件中切換兩個 Icon 就完成了

最後再看一下效果:

Flutter | 求求你們了,切換 Widget 的時候加上動畫吧

總結

使用該控制元件最應該注意的點就是 Key 的問題,一定要記住:

如果新 Widget 和 舊 Widget 的型別和鍵相同,但是引數不同,那麼也不會進行轉換。如果想要進行轉換,那麼要新增一個 Key。

完整程式碼已經傳至GitHub:github.com/wanglu1209/…

Flutter | 求求你們了,切換 Widget 的時候加上動畫吧

相關文章