精心設計的動畫讓 UI 感覺更直觀,有助於打造精緻應用的流暢外觀和感覺,並改善使用者體驗。Flutter 的動畫支援使得實現各種動畫型別變得容易。許多小部件,特別是Material 小部件,都附帶了其設計規範中定義的標準運動效果,但也可以自定義這些效果。

選擇一種方法

#

在 Flutter 中建立動畫時,可以採用不同的方法。哪種方法適合你?為了幫助你做出決定,請觀看影片《如何選擇適合你的 Flutter 動畫小部件?》(也作為一篇配套文章釋出。)

在新標籤頁中觀看 YouTube 影片:“如何選擇適合您的 Flutter 動畫小部件?”

(要深入瞭解決策過程,請觀看 Flutter Europe 上釋出的影片《正確使用 Flutter 動畫》。)

如影片所示,以下決策樹可幫助您決定在實現 Flutter 動畫時採用哪種方法。

The animation decision tree

動畫深入解析

#

要更深入地瞭解 Flutter 動畫的工作原理,請觀看動畫深入解析。(也作為配套文章釋出。)

在新標籤頁中觀看 YouTube 影片:“深入瞭解 Flutter 動畫”

隱式和顯式動畫

#

預封裝的隱式動畫

#

如果預封裝的隱式動畫(最容易實現的動畫)符合您的需求,請觀看隱式動畫基礎知識。(也作為配套文章釋出。)

在新標籤頁中觀看 YouTube 影片:“Flutter 隱式動畫基礎知識”

自定義隱式動畫

#

要建立自定義隱式動畫,請觀看使用 TweenAnimationBuilder 建立您自己的自定義隱式動畫。(也作為配套文章釋出。)

在新標籤頁中觀看 YouTube 影片:“使用 TweenAnimationBuilder 建立自定義隱式動畫”

內建隱式動畫

#

要建立顯式動畫(您控制動畫,而不是讓框架控制它),也許可以使用內建的顯式動畫類之一。欲瞭解更多資訊,請觀看使用內建顯式動畫製作您的第一個定向動畫。(也作為配套文章釋出。)

在新標籤頁中觀看 YouTube 影片:“使用內建顯式動畫製作您的第一個定向動畫”

顯式動畫

#

如果您需要從頭開始構建顯式動畫,請觀看使用 AnimatedBuilder 和 AnimatedWidget 建立自定義顯式動畫。(也作為配套文章釋出。)

在新標籤頁中觀看 YouTube 影片:“使用 AnimatedBuilder 和 AnimatedWidget 建立自定義顯式動畫”

動畫型別

#

通常,動畫要麼是補間動畫,要麼是基於物理的動畫。以下部分解釋了這些術語的含義,併為您提供了可以瞭解更多資訊的資源。

補間動畫

#

“補間”是“in-betweening”的縮寫。在補間動畫中,定義了起始點和結束點,以及時間線和定義過渡時序和速度的曲線。框架計算如何從起始點過渡到結束點。

基於物理的動畫

#

在基於物理的動畫中,運動被模擬成類似於真實世界的行為。例如,當你丟擲一個球時,它在哪裡以及何時落地取決於拋球的速度以及它離地面的距離。同樣,一個系在彈簧上的球落地(並彈跳)的方式與一個系在繩子上的球落地的方式不同。

常見動畫模式

#

大多數 UX 或動效設計師發現,在設計 UI 時,某些動畫模式被重複使用。本節列出了一些常用的動畫模式,並告訴您在哪裡可以學到更多。

動畫列表或網格

#

這種模式涉及對列表中或網格中元素的新增或刪除進行動畫處理。

  • AnimatedList 示例
    此演示來自 示例應用目錄,展示瞭如何動畫新增元素到列表或移除選定元素。當用戶使用加號 (+) 和減號 (-) 按鈕修改列表時,內部 Dart 列表會同步。

共享元素過渡

#

在此模式中,使用者從頁面中選擇一個元素(通常是影像),然後 UI 將選定的元素動畫到包含更多詳細資訊的新頁面。在 Flutter 中,您可以使用 `Hero` 小部件輕鬆實現路由(頁面)之間的共享元素過渡。

  • 英雄動畫 如何建立兩種風格的英雄動畫

    • 英雄在改變位置和大小的同時從一個頁面飛向另一個頁面。
    • 英雄的邊界在從一個頁面飛向另一個頁面時,從圓形變為方形。
  • 另請參閱 HeroNavigatorPageRoute 類的 API 文件。

交錯動畫

#

動畫被分解成更小的動作,其中一些動作被延遲。這些較小的動畫可能是順序的,也可能部分或完全重疊。

基本動畫概念和類

#

Flutter 中的動畫系統基於型別化的 Animation 物件。小部件可以直接在它們的 build 函式中透過讀取其當前值並監聽其狀態變化來整合這些動畫,或者它們可以使用這些動畫作為更精細動畫的基礎,然後將這些動畫傳遞給其他小部件。

Animation<double>

#

在 Flutter 中,一個 Animation 物件對螢幕上顯示的內容一無所知。Animation 是一個抽象類,它瞭解其當前值和狀態(已完成或已取消)。最常用的動畫型別之一是 Animation<double>

一個 Animation 物件在特定持續時間內按順序生成兩個值之間的插值數字。Animation 物件的輸出可以是線性的、曲線的、階梯函式或您可以建立的任何其他對映。根據 Animation 物件的控制方式,它可以反向執行,甚至在中間切換方向。

動畫也可以插值除了 double 之外的其他型別,例如 Animation<Color>Animation<Size>

一個 Animation 物件擁有狀態。它的當前值始終在 .value 成員中可用。

Animation 物件對渲染或 build() 函式一無所知。

CurvedAnimation

#

CurvedAnimation 將動畫進度定義為非線性曲線。

dart
animation = CurvedAnimation(parent: controller, curve: Curves.easeIn);

CurvedAnimationAnimationController(在接下來的章節中描述)都屬於 Animation<double> 型別,因此它們可以互換使用。CurvedAnimation 包裝它正在修改的物件——你不需要透過子類化 AnimationController 來實現曲線。

您可以將 CurvesCurvedAnimation 配合使用。Curves 類定義了許多常用的曲線,或者您可以建立自己的曲線。例如:

dart
import 'dart:math';

class ShakeCurve extends Curve {
  @override
  double transform(double t) => sin(t * pi * 2);
}

如果你想將動畫曲線應用於 Tween,請考慮使用 CurveTween

AnimationController

#

AnimationController 是一個特殊的 Animation 物件,每當硬體準備好新幀時,它就會生成一個新值。預設情況下,AnimationController 在給定持續時間內線性地生成從 0.0 到 1.0 的數字。例如,此程式碼建立一個 Animation 物件,但不會啟動它執行:

dart
controller = AnimationController(
  duration: const Duration(seconds: 2),
  vsync: this,
);

AnimationController 派生自 Animation<double>,因此可以在需要 Animation 物件的地方使用它。但是,AnimationController 具有控制動畫的附加方法。例如,您可以使用 .forward() 方法啟動動畫。數字的生成與螢幕重新整理相關聯,因此通常每秒生成 60 個數字。生成每個數字後,每個 Animation 物件都會呼叫附加的 Listener 物件。要為每個子項建立自定義顯示列表,請參閱 RepaintBoundary

建立 AnimationController 時,您會為其傳遞一個 vsync 引數。vsync 的存在可以防止螢幕外動畫消耗不必要的資源。您可以透過將 SingleTickerProviderStateMixin 新增到類定義中,將您的有狀態物件用作 vsync。您可以在 GitHub 上的 animate1 中看到一個示例。

Tween

#

預設情況下,AnimationController 物件的範圍從 0.0 到 1.0。如果您需要不同的範圍或不同的資料型別,可以使用 Tween 來配置動畫以插值到不同的範圍或資料型別。例如,下面的 Tween 從 -200.0 到 0.0:

dart
tween = Tween<double>(begin: -200, end: 0);

Tween 是一個無狀態物件,只接受 beginendTween 的唯一作用是定義從輸入範圍到輸出範圍的對映。輸入範圍通常是 0.0 到 1.0,但這並非強制要求。

一個 Tween 繼承自 Animatable<T>,而不是 Animation<T>。一個 Animatable,像 Animation 一樣,不一定輸出 double。例如,ColorTween 指定了兩種顏色之間的漸變。

dart
colorTween = ColorTween(begin: Colors.transparent, end: Colors.black54);

Tween 物件不儲存任何狀態。相反,它提供了 evaluate(Animation<double> animation) 方法,該方法使用 transform 函式將動畫的當前值(介於 0.0 和 1.0 之間)對映到實際的動畫值。

Animation 物件的當前值可以在 .value 方法中找到。evaluate 函式還執行一些內務管理,例如確保當動畫值分別為 0.0 和 1.0 時返回 begin 和 end。

Tween.animate

#

要使用 Tween 物件,請在 Tween 上呼叫 animate(),並傳入控制器物件。例如,以下程式碼在 500 毫秒內生成從 0 到 255 的整數值。

dart
AnimationController controller = AnimationController(
  duration: const Duration(milliseconds: 500),
  vsync: this,
);
Animation<int> alpha = IntTween(begin: 0, end: 255).animate(controller);

以下示例展示了一個控制器、一條曲線和一個 Tween

dart
AnimationController controller = AnimationController(
  duration: const Duration(milliseconds: 500),
  vsync: this,
);
final Animation<double> curve = CurvedAnimation(
  parent: controller,
  curve: Curves.easeOut,
);
Animation<int> alpha = IntTween(begin: 0, end: 255).animate(curve);

動畫通知

#

一個 Animation 物件可以有 Listeners 和 StatusListeners,透過 addListener()addStatusListener() 定義。當動畫的值改變時,就會呼叫 ListenerListener 最常見的行為是呼叫 setState() 來觸發重建。當動畫開始、結束、向前或向後移動時,就會呼叫 StatusListener,這由 AnimationStatus 定義。

程式碼實驗室、教程和文章

#

以下資源是學習 Flutter 動畫框架的良好起點。每個文件都展示瞭如何編寫動畫程式碼。

  • 隱式動畫程式碼實驗室
    透過分步說明和互動式示例,涵蓋如何使用隱式動畫。

  • 動畫教程
    解釋了 Flutter 動畫包中的基本類(控制器、Animatable、曲線、監聽器、構建器),並指導您逐步完成使用動畫 API 不同方面的補間動畫。本教程展示瞭如何建立您自己的自定義顯式動畫。

  • Flutter 從零到一,第一部分第二部分
    Medium 文章,展示瞭如何使用補間動畫建立動畫圖表。

  • 休閒遊戲工具包
    一個包含遊戲模板的工具包,其中包含如何使用 Flutter 動畫的示例。

其他資源

#

請透過以下連結瞭解更多 Flutter 動畫知識