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

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

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

相似於這樣的:github

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

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

AnimatedSwitcher 瞭解一下。ide

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.ui

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).this

大體意思就是:

默認狀況下是執行透明度的動畫。

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

若是新 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 就完成了

最後再看一下效果:

總結

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

若是新 Widget 和 舊 Widget 的類型和鍵相同,可是參數不一樣,那麼也不會進行轉換。若是想要進行轉換,那麼要添加一個 Key。

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

相關文章
相關標籤/搜索