動畫簡介
如何在 Flutter 中執行動畫。
精心設計的動畫可以使 UI 感覺更直觀,有助於提升應用程式的流暢外觀和感覺,並改善使用者體驗。Flutter 的動畫支援使實現各種動畫型別變得容易。許多小部件,尤其是 Material 小部件,都帶有其設計規範中定義的標準運動效果,但也可以自定義這些效果。
選擇方法
#在 Flutter 中建立動畫時,您可以採用不同的方法。哪種方法適合您?為了幫助您決定,請觀看影片 如何選擇正確的 Flutter 動畫小部件?(也以 配套文章 的形式釋出。)
(要更深入地瞭解決策過程,請觀看在 Flutter Europe 上展示的 Flutter 中正確的動畫 影片。)
如影片所示,以下決策樹可幫助您決定在實現 Flutter 動畫時使用哪種方法
動畫深入探討
#要更深入地瞭解動畫在 Flutter 中是如何工作的,請觀看 動畫深入探討。(也以 配套文章 的形式釋出。)
隱式和顯式動畫
#預封裝的隱式動畫
#如果預封裝的隱式動畫(最容易實現的動畫)滿足您的需求,請觀看 使用隱式動畫進行動畫基礎。(也以 配套文章 的形式釋出。)
自定義隱式動畫
#要建立自定義隱式動畫,請觀看 使用 TweenAnimationBuilder 建立您自己的自定義隱式動畫。(也以 配套文章 的形式釋出。)
內建的顯式動畫
#要建立顯式動畫(您控制動畫,而不是讓框架控制它),也許可以使用內建的顯式動畫類之一。有關更多資訊,請觀看 使用內建顯式動畫製作您的第一個定向動畫。(也以 配套文章 的形式釋出。)
顯式動畫
#如果您需要從頭開始構建顯式動畫,請觀看 使用 AnimatedBuilder 和 AnimatedWidget 建立自定義顯式動畫。(也以 配套文章 的形式釋出。)
動畫型別
#通常,動畫要麼是補間動畫,要麼是基於物理的動畫。以下部分解釋了這些術語的含義,併為您提供瞭解更多資訊的資源。
補間動畫
#在兩幀之間插值 的縮寫。在補間動畫中,定義了起點和終點,以及一個時間線和一個定義過渡的時間和速度的曲線。框架計算如何從起點過渡到終點。
-
請參閱 動畫教程,其中示例使用了補間動畫。
-
另請參閱
Tween、CurveTween和TweenSequence的 API 文件。
基於物理的動畫
#在基於物理的動畫中,運動被建模為類似於現實世界中的行為。例如,您扔一個球時,它著陸的位置和時間取決於它被扔的速度以及距離地面的距離。同樣,掉落連線到彈簧上的球的下落(和反彈)與掉落連線到繩子上的球不同。
-
使用物理模擬來為元件新增動畫
Flutter cookbook 動畫部分中的一個示例。 -
另請參閱
AnimationController.animateWith和SpringSimulation的 API 文件。
常見的動畫模式
#大多數 UX 或運動設計師發現,在設計 UI 時,某些動畫模式會被重複使用。本節列出了一些常用的動畫模式,並告訴您在哪裡可以瞭解更多資訊。
動畫列表或網格
#此模式涉及動畫化列表或網格中元素的新增或刪除。
-
AnimatedList示例
來自 示例應用程式目錄 的此演示展示瞭如何動畫化地將元素新增到列表中或刪除選定的元素。內部 Dart 列表與使用者使用加號 (+) 和減號 (-) 按鈕修改列表時同步。
共享元素過渡
#在此模式中,使用者從頁面中選擇一個元素(通常是影像),並且 UI 將選定的元素動畫化到包含更多詳細資訊的頁面。在 Flutter 中,您可以使用 Hero 小部件輕鬆地在路由(頁面)之間實現共享元素過渡。
-
Hero 動畫 如何建立兩種風格的 Hero 動畫
- 英雄從一個頁面飛到另一個頁面,同時改變位置和大小。
- 英雄的邊界在從一個頁面飛到另一個頁面的過程中改變形狀,從圓形變為方形。
交錯動畫
#動畫被分解成較小的運動,其中一些運動被延遲。較小的動畫可能是順序的,或者可能部分或完全重疊。
必要的動畫概念和類
#Flutter 中的動畫系統基於型別的 Animation 物件。小部件可以直接在其構建函式中透過讀取其當前值和監聽其狀態更改來合併這些動畫,或者它們可以將動畫作為傳遞給其他小部件的更精細動畫的基礎。
Animation<double>
#在 Flutter 中,Animation 物件不知道螢幕上有什麼。Animation 是一個抽象類,它瞭解其當前值和狀態(已完成或已取消)。一種更常用的動畫型別是 Animation<double>。
Animation 物件按順序生成給定持續時間內的兩個值之間的插值數字。Animation 物件的輸出可以是線性的、曲線的、步進函式或您可以建立的任何對映。根據 Animation 物件如何控制,它可以在反向執行,甚至在中間改變方向。
動畫也可以插值其他型別,例如 Animation<Color> 或 Animation<Size>。
Animation 物件具有狀態。其當前值始終在 .value 成員中可用。
Animation 物件不知道渲染或 build() 函式。
CurvedAnimation
#一個 CurvedAnimation 將動畫的進度定義為非線性曲線。
animation = CurvedAnimation(parent: controller, curve: Curves.easeIn);
CurvedAnimation 和 AnimationController(在下一節中描述)都是 Animation<double> 型別,因此您可以互換地傳遞它們。CurvedAnimation 包裝它正在修改的物件——您不需要繼承 AnimationController 來實現曲線。
您可以使用 Curves 與 CurvedAnimation。Curves 類定義了許多常用的曲線,或者您可以建立自己的曲線。例如
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 物件,但不啟動它
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
tween = Tween<double>(begin: -200, end: 0);
Tween 是一個無狀態物件,它僅接受 begin 和 end。Tween 的唯一工作是定義從輸入範圍到輸出範圍的對映。輸入範圍通常為 0.0 到 1.0,但這不是必需的。
Tween 繼承自 Animatable<T>,而不是 Animation<T>。Animatable,就像 Animation 一樣,不必輸出 double。例如,ColorTween 指定兩個顏色之間的漸變。
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 的整數值。
AnimationController controller = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
);
Animation<int> alpha = IntTween(begin: 0, end: 255).animate(controller);
以下示例顯示了一個控制器、一個曲線和一個 Tween
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 物件可以擁有 Listener 和 StatusListener,分別使用 addListener() 和 addStatusListener() 定義。每當動畫值發生變化時,都會呼叫一個 Listener。Listener 最常見的行為是呼叫 setState() 以導致重建。當動畫開始、結束、前進或反向移動時,會呼叫一個 StatusListener,具體由 AnimationStatus 定義。
Codelabs、教程和文章
#以下資源是學習 Flutter 動畫框架的好地方。這些文件中的每一個都展示瞭如何編寫動畫程式碼。
-
Flutter 動畫 codelab
在構建一個多項選擇題遊戲的同時,瞭解隱式動畫和顯式動畫。 -
動畫教程
在指導您使用動畫 API 的不同方面進行漸變動畫的同時,解釋了 Flutter 動畫包中的基本類(控制器、Animatable、曲線、監聽器、構建器)。本教程展示瞭如何建立您自己的自定義顯式動畫。 -
Zero to One with Flutter,第一部分 和 第二部分
Medium 文章,展示瞭如何使用漸變動畫建立動畫圖表。 -
休閒遊戲工具包
一個包含遊戲模板的工具包,其中包含如何使用 Flutter 動畫的示例。
其他資源
#在以下連結中瞭解有關 Flutter 動畫的更多資訊