(Flutter)交錯(cuò)動(dòng)畫(huà)【譯】

交錯(cuò)動(dòng)畫(huà)

你將學(xué)習(xí)到什么:

  • 交錯(cuò)動(dòng)畫(huà)由序列或重疊的動(dòng)畫(huà)組成。
  • 要?jiǎng)?chuàng)建交錯(cuò)動(dòng)畫(huà),使用多個(gè)動(dòng)畫(huà)對(duì)象。
  • 一個(gè)AnimationController控制所有動(dòng)畫(huà)。
  • 每個(gè)動(dòng)畫(huà)對(duì)象在間隔期間指定動(dòng)畫(huà)。
  • 對(duì)于要設(shè)置動(dòng)畫(huà)的每個(gè)屬性,請(qǐng)創(chuàng)建一個(gè)Tween。

Terminology: 如果補(bǔ)間或補(bǔ)間的概念對(duì)您來(lái)說(shuō)是新的,請(qǐng)參閱Flutter教程中的動(dòng)畫(huà)

交錯(cuò)的動(dòng)畫(huà)是一個(gè)直截了當(dāng)?shù)母拍睿阂曈X(jué)變化發(fā)生在一系列操作中,而不是一次性發(fā)生。 動(dòng)畫(huà)可能是純粹順序的,在下一個(gè)動(dòng)畫(huà)之后會(huì)發(fā)生一次更改,或者可能部分或完全重疊。 它也可能有間隙,沒(méi)有發(fā)生變化。

本指南介紹了如何在Flutter中構(gòu)建交錯(cuò)動(dòng)畫(huà)。

Examples

本指南介紹了basic_staggered_animation示例。您還可以參考更復(fù)雜的示例staggered_pic_selection。
basic_staggered_animation

顯示單個(gè)窗口小部件的一系列連續(xù)和重疊動(dòng)畫(huà)。 點(diǎn)擊屏幕會(huì)開(kāi)始一個(gè)動(dòng)畫(huà),可以改變不透明度,大小,形狀,顏色和填充。

staggered_pic_selection

顯示從以三種尺寸之一顯示的圖像列表中刪除圖像。此示例使用兩個(gè)動(dòng)畫(huà)控制器: 一個(gè)用于圖像選擇/取消選擇,另一個(gè)用于圖像刪除。 選擇/取消選擇動(dòng)畫(huà)是錯(cuò)開(kāi)的。 (要查看此效果,您可能需要增加timeDilation 值。) 選擇一個(gè)最大的圖像,它會(huì)縮小,因?yàn)樗谒{(lán)色圓圈內(nèi)顯示一個(gè)復(fù)選標(biāo)記。 接下來(lái),選擇一個(gè)最小的圖像,當(dāng)復(fù)選標(biāo)記消失時(shí),大圖像會(huì)擴(kuò)展。 在大圖像完成展開(kāi)之前,小圖像會(huì)縮小以顯示其復(fù)選標(biāo)記。 這種交錯(cuò)行為類(lèi)似于您在Google相冊(cè)中看到的行為。

以下視頻演示了basic_staggered_animation執(zhí)行的動(dòng)畫(huà):


StaggerDemo.gif

在視頻中,您會(huì)看到單個(gè)小部件的以下動(dòng)畫(huà),該小部件以帶有略微圓角的邊框藍(lán)色方塊開(kāi)始。 該方塊按以下順序運(yùn)行更改:

  1. 淡入
  2. 擴(kuò)大
  3. 向上移動(dòng)時(shí)變得更高
  4. 轉(zhuǎn)變?yōu)橛羞吔绲膱A圈
  5. 將顏色更改為橙??色

向前跑之后,動(dòng)畫(huà)反向運(yùn)行。

Flutter新手?
本頁(yè)假定您知道如何使用Flutter的小部件創(chuàng)建布局。 有關(guān)更多信息,請(qǐng)參閱在Flutter中構(gòu)建布局.

交錯(cuò)動(dòng)畫(huà)的基本結(jié)構(gòu)

重點(diǎn)是什么?

  • 所有動(dòng)畫(huà)都由同一個(gè)AnimationController驅(qū)動(dòng)。
  • 無(wú)論動(dòng)畫(huà)實(shí)時(shí)持續(xù)多長(zhǎng)時(shí)間,控制器的值必須介于0.0和1.0之間。
  • 每個(gè)動(dòng)畫(huà)的間隔介于0.0和1.0之間。
  • 對(duì)于在間隔中設(shè)置動(dòng)畫(huà)的每個(gè)屬性,請(qǐng)創(chuàng)建一個(gè)Tween。 Tween指定該屬性的開(kāi)始值和結(jié)束值。
  • Tween生成一個(gè)由控制器管理的Animation對(duì)象。

下圖顯示了basic_staggered_animation示例中使用的間隔。 您可能會(huì)注意到以下特征:

  • 不透明度在時(shí)間軸的前10%期間發(fā)生變化。
  • 不透明度的變化與寬度的變化之間存在微小的差距。
  • 在最后25%的時(shí)間線中沒(méi)有任何動(dòng)畫(huà)。
  • 增加填充使小部件看起來(lái)向上。
  • 將邊框半徑增加到0.5,將帶圓角的方形轉(zhuǎn)換為圓形。
  • 填充和邊界半徑變化發(fā)生在相同的精確間隔期間,但它們不必。
StaggeredAnimationIntervals.png

要設(shè)置動(dòng)畫(huà):

  • 創(chuàng)建一個(gè)管理所有動(dòng)畫(huà)的AnimationController。
  • 為每個(gè)動(dòng)畫(huà)屬性創(chuàng)建一個(gè)Tween。
    • Tween定義了一系列值。
    • Tween的animate方法需要parent控制器,并為該屬性生成一個(gè)Animation。
  • 在動(dòng)畫(huà)curve屬性上指定間隔。

當(dāng)控制動(dòng)畫(huà)的值更改時(shí),新動(dòng)畫(huà)的值會(huì)更改,從而觸發(fā)UI更新。

以下代碼為width屬性創(chuàng)建補(bǔ)間。 它構(gòu)建一個(gè)CurvedAnimation ,指定一個(gè)緩和的曲線。 有關(guān)其他可用的預(yù)定義動(dòng)畫(huà)曲線,請(qǐng)參閱曲線。

width = Tween<double>(
  begin: 50.0,
  end: 150.0,
).animate(
  CurvedAnimation(
    parent: controller,
    curve: Interval(
      0.125, 0.250,
      curve: Curves.ease,
    ),
  ),
),

beginend 的值不必是雙倍的。下面的代碼使用BorderRadius.circular()borderRadius屬性(控制方塊角的圓度)構(gòu)建補(bǔ)間。

borderRadius = BorderRadiusTween(
  begin: BorderRadius.circular(4.0),
  end: BorderRadius.circular(75.0),
).animate(
  CurvedAnimation(
    parent: controller,
    curve: Interval(
      0.375, 0.500,
      curve: Curves.ease,
    ),
  ),
),

完成交錯(cuò)的動(dòng)畫(huà)

與所有交互式小部件一樣,完整的動(dòng)畫(huà)由小部件對(duì)組成:無(wú)狀態(tài)小部件和有狀態(tài)小部件。

無(wú)狀態(tài)窗口小部件指定補(bǔ)間,定義Animation對(duì)象,并提供build()函數(shù),負(fù)責(zé)構(gòu)建窗口小部件樹(shù)的動(dòng)畫(huà)部分。

有狀態(tài)小部件創(chuàng)建控制器,播放動(dòng)畫(huà),并構(gòu)建小部件樹(shù)的非動(dòng)畫(huà)部分。 在屏幕中的任何位置檢測(cè)到點(diǎn)擊時(shí),動(dòng)畫(huà)開(kāi)始。

basic_staggered_animation’s main.dart的完整代碼

無(wú)狀態(tài)小部件:StaggerAnimation

在無(wú)狀態(tài)小部件StaggerAnimation中, build()函數(shù)實(shí)例化一個(gè)AnimatedBuilder - 一個(gè)用于構(gòu)建動(dòng)畫(huà)的通用小部件。 AnimatedBuilder構(gòu)建一個(gè)小部件并使用Tweens的當(dāng)前值配置它。 該示例創(chuàng)建一個(gè)名為_buildAnimation()的函數(shù)(執(zhí)行實(shí)際的UI更新),并將其分配給其builder屬性。 AnimatedBuilder監(jiān)聽(tīng)來(lái)自動(dòng)畫(huà)控制器的通知,在值發(fā)生變化時(shí)將小部件樹(shù)標(biāo)記為臟。 對(duì)于動(dòng)畫(huà)的每個(gè)刻度,值都會(huì)更新,從而調(diào)用_buildAnimation() 。

class StaggerAnimation extends StatelessWidget {
  StaggerAnimation({ Key key, this.controller }) :

    // Each animation defined here transforms its value during the subset
    // of the controller's duration defined by the animation's interval.
    // For example the opacity animation transforms its value during
    // the first 10% of the controller's duration.

    opacity = Tween<double>(
      begin: 0.0,
      end: 1.0,
    ).animate(
      CurvedAnimation(
        parent: controller,
        curve: Interval(
          0.0, 0.100,
          curve: Curves.ease,
        ),
      ),
    ),

    // ... Other tween definitions ...

    super(key: key);

  final Animation<double> controller;
  final Animation<double> opacity;
  final Animation<double> width;
  final Animation<double> height;
  final Animation<EdgeInsets> padding;
  final Animation<BorderRadius> borderRadius;
  final Animation<Color> color;

  // This function is called each time the controller "ticks" a new frame.
  // When it runs, all of the animation's values will have been
  // updated to reflect the controller's current value.
  Widget _buildAnimation(BuildContext context, Widget child) {
    return Container(
      padding: padding.value,
      alignment: Alignment.bottomCenter,
      child: Opacity(
        opacity: opacity.value,
        child: Container(
          width: width.value,
          height: height.value,
          decoration: BoxDecoration(
            color: color.value,
            border: Border.all(
              color: Colors.indigo[300],
              width: 3.0,
            ),
            borderRadius: borderRadius.value,
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      builder: _buildAnimation,
      animation: controller,
    );
  }
}

有狀態(tài)小部件:StaggerDemo

有狀態(tài)小部件StaggerDemo創(chuàng)建了AnimationController(規(guī)定他們的對(duì)象),指定持續(xù)時(shí)間為2000毫秒。 它播放動(dòng)畫(huà),并構(gòu)建小部件樹(shù)的非動(dòng)畫(huà)部分。 在屏幕中檢測(cè)到點(diǎn)擊時(shí)動(dòng)畫(huà)開(kāi)始。 動(dòng)畫(huà)向前,然后向后。

class StaggerDemo extends StatefulWidget {
  @override
  _StaggerDemoState createState() => _StaggerDemoState();
}

class _StaggerDemoState extends State<StaggerDemo> with TickerProviderStateMixin {
  AnimationController _controller;

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

    _controller = AnimationController(
      duration: const Duration(milliseconds: 2000),
      vsync: this
    );
  }

  // ...Boilerplate...

  Future<Null> _playAnimation() async {
    try {
      await _controller.forward().orCancel;
      await _controller.reverse().orCancel;
    } on TickerCanceled {
      // the animation got canceled, probably because we were disposed
    }
  }

  @override
  Widget build(BuildContext context) {
    timeDilation = 10.0; // 1.0 is normal animation speed.
    return Scaffold(
      appBar: AppBar(
        title: const Text('Staggered Animation'),
      ),
      body: GestureDetector(
        behavior: HitTestBehavior.opaque,
        onTap: () {
          _playAnimation();
        },
        child: Center(
          child: Container(
            width: 300.0,
            height: 300.0,
            decoration: BoxDecoration(
              color: Colors.black.withOpacity(0.1),
              border: Border.all(
                color:  Colors.black.withOpacity(0.5),
              ),
            ),
            child: StaggerAnimation(
              controller: _controller.view
            ),
          ),
        ),
      ),
    );
  }
}

資源

編寫(xiě)動(dòng)畫(huà)時(shí),以下資源可能會(huì)有所幫助:

Animations landing page

列出Flutter動(dòng)畫(huà)的可用文檔。 如果補(bǔ)間對(duì)您來(lái)說(shuō)不熟悉,請(qǐng)查看動(dòng)畫(huà)教程 。

Flutter API documentation

所有Flutter庫(kù)的參考文檔。 特別是,請(qǐng)參閱動(dòng)畫(huà)庫(kù)文檔。

Flutter Gallery

演示應(yīng)用程序展示了許多材料組件和其他Flutter功能。 Shrine demo實(shí)現(xiàn)了英雄動(dòng)畫(huà)。

Material motion spec

描述材料應(yīng)用的動(dòng)作。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 天空灰的發(fā)白 就像兔子的尾巴 沖出象牙之口 想象沒(méi)有辦法舒展 龍川之水 流淌著工業(yè)的源頭 儀器與價(jià)值的比重 顛覆嘈...
    讀叔閱讀 440評(píng)論 0 1
  • 清晨,開(kāi)車(chē)途中,聽(tīng)起了《蔣勛七講》中的第一講,每天留出18分鐘來(lái)讀詩(shī)。 于是,我聽(tīng)到了這首月圓夜,蔣勛讀的詩(shī): 《...
    蛻變的林林閱讀 339評(píng)論 0 1
  • 什么時(shí)候都不會(huì)太遲 老了,也能和伴侶一起爬山,一起嘮嗑。 想要出發(fā)永遠(yuǎn)不會(huì)太遲。 三五好友,不用一壺酒,不用...
    二十二秋初閱讀 420評(píng)論 0 0

友情鏈接更多精彩內(nèi)容