在開始研究FireMonkey提供的動畫組件前,回顧一下多數時候,只是想給控件加一些突出的提醒或點綴,所以無須真的添加一個動畫組件。FMX(FireMonkey的簡稱)提供了一系列便利的操作。
本節將介紹:
- 使用TFmxObject的動畫函數。
- 使用TAnimator對象快速創建動畫。
- TAnimator與其他的TAnimation動畫組件的區別。
1. 使用FmxObject創建動畫。
TFmxObject是位於TComponent和TControl類之間的一個提供組件呈現的中間類,這是將控件的視覺部分與行為部分進行分離的一箇中間類。
TFmxObject 是 FireMonkey (FMX) 框架中幾乎所有可視和非可視組件的基類。它不負責具體的渲染(那是 TControl 及其子類的工作),而是提供了構建整個 FMX 應用程序對象模型所需的核心基礎功能。

本圖來自《Delphi GUI Programming with FireMonkey》
1. 打開Delphi 12.3,在窗體上放一個TRectangle控件和2個Button,表單佈局如下圖:

2. 分別為按鈕1和按鈕2添加如下的事件處理代碼,來快速實現動畫效果。
// 功能:改變一個矩形的透明度,實現淡入淡出效果。
procedure TFormMain.Button1Click(Sender: TObject);
begin
// 直接調用 Rectangle1 對象的 AnimateFloat 方法(內部實際調用TAnimator.AnimateFloat 類似)
// 參數1 ('Opacity'): 要動畫化的屬性名稱,這裏是透明度屬性(0為完全透明,1為完全不透明)
// 參數2 (0.5): 動畫的最終目標值,將透明度變化至 0.5(半透明)
// 參數3 (2): 動畫的持續時間,單位為秒,即動畫在 2 秒內緩慢完成
// 參數4 (TAnimationType.InOut): 動畫曲線。InOut 表示動畫開始和結束時都較緩慢,中間較快
// 參數5 (TInterpolationType.Linear): 插值類型。線性插值,變化均勻
Rectangle1.AnimateFloat('Opacity', 0.5, 2, TAnimationType.InOut,
TInterpolationType.Linear);
end;
// 功能:改變一個矩形的填充顏色。
procedure TFormMain.Button2Click(Sender: TObject);
begin
// 調用 Rectangle1 對象的 AnimateColor 方法,專門用於對顏色屬性進行動畫處理
// 參數1 ('Fill.Color'): 要動畫化的屬性名稱,這裏是填充色的顏色屬性
// 參數2 ($FF0003F3): 動畫的最終目標顏色值。這是一個十六進制的 TAlphaColor 值。
// $FF 表示完全不透明(Alpha通道)
// $0003F3 表示 RGB 顏色分量,此代碼為一種藍色
// 參數3 (2): 動畫的持續時間,2秒
// 參數4 (TAnimationType.InOut): InOut 動畫曲線
// 參數5 (TInterpolationType.Linear): 線性插值,顏色會均勻過渡
Rectangle1.AnimateColor('Fill.Color', $FF0003F3, 2, TAnimationType.InOut,
TInterpolationType.Linear);
end;
運行效果如下所示:

AnimateFloat和AnimateColor分別對Trectangle的屬性Opacity和Fill.Color設置了新的會睛,Duration指示動畫的持續時間為2秒,最後指定了動畫曲線和插值算法,在稍後的內容中會介紹。
如果查看這2個方法的定義,可以看到最終還是調用了TAnimator的相應的類方法:

在方法定義部分,可以看到Delphi建議使用TAnimator來替代使用這裏的方法,接下來將使用TAnimator來創建摺疊動畫。
2. 使用TAnimator創建摺疊動畫。
3. 在主窗體上放一個新的TLayout控件,使其align為left,然後在裏邊分別放一個TRectangle、TVertScrollBox,幾個TLabel組件,以及相應的按鈕。Structure和表單結構如下圖。
注意:需要為TRectangle容器指定Hight為250,接下來編程時會進行控制。

首先在代碼中的uses區中添加“FMX.Ani”,這是TAnimation和TAnimator組件所在的單元。
接下來為按鈕事件添加如下的事件處理代碼:
procedure TFormMain.BtnActionClick(Sender: TObject);
begin
// 使用 if 語句判斷名為 RctAnimate 的矩形控件的當前高度是否等於 250 像素
// 這個值代表矩形的"展開"狀態高度
if RctAnimate.Height = 250 then
begin
// 如果當前是展開狀態(高度為250),則執行摺疊動畫
// 使用 FireMonkey 的 TAnimator 類來創建並執行一個浮點屬性動畫
// 參數1 (RctAnimate): 指定要應用動畫的目標對象,這裏是 RctAnimate 矩形
// 參數2 ('Height'): 指定要動畫化的屬性名稱,這裏是高度屬性
// 參數3 (100): 動畫的結束值,將高度動畫變化到 100 像素(摺疊狀態)
// 參數4 (0.8): 動畫的持續時間,單位為秒,表示動畫將在 0.8 秒內完成
// 參數5 (TAnimationType.&In): 動畫的緩動效果類型。&In 表示動畫開始時較慢,然後加速
// (& 符號是必需的,因為 'In' 是 Delphi 的保留關鍵字)
// 參數6 (TInterpolationType.Linear): 插值類型。Linear 表示線性插值,即數值均勻變化
TAnimator.AnimateFloat(RctAnimate, 'Height', 100, 0.8,
TAnimationType.&In, TInterpolationType.Linear);
// 動畫開始後,同時更新按鈕的顯示文本為"展開"
// 這為用户提供了視覺反饋,表明下次點擊此按鈕將會執行展開操作
BtnAction.Text := '展開';
end
else // 如果 RctAnimate 的高度不等於 250 像素(即當前處於摺疊或其他狀態)
begin
// 執行展開動畫,將矩形的高度從當前值動畫變化到 250 像素
// 使用相同的 TAnimator.AnimateFloat 方法,但目標值改為 250
TAnimator.AnimateFloat(RctAnimate, 'Height', 250, 0.8,
TAnimationType.&In, TInterpolationType.Linear);
// 將按鈕的文本更新為"摺疊",提示用户下次點擊將會摺疊矩形
BtnAction.Text := '摺疊';
end;
end;
運行效果如下所示:

可以看到簡單幾行代碼應實現了動畫的摺疊效果。
Show Scroll Bar複選框用來確定是否為TVertScrollBox顯示滾動條,代碼如下所示:
procedure TFormMain.CheckBox1Change(Sender: TObject);
begin
if CheckBox1.IsChecked = True then
VertScrollBoxClient.ShowScrollBars := CheckBox1.IsChecked
else
VertScrollBoxClient.ShowScrollBars := CheckBox1.IsChecked;
end;
3.TAnimator與其他的動畫組件的區別在哪裏?
-
TAnimator像一個臨時工,你叫他來完成一個一次性任務(動畫),他幹完活就走,不留痕跡。特點是簡單、快捷、無需管理。
-
TAnimation 組件像一個正式員工,你需要僱傭(創建)他,給他安排詳細的崗位職責(配置屬性),並且要管理他的去留(生命週期)。特點是功能強大、可配置性高、需手動管理。
- 當在如下情形時,選擇TAnimator:
-
動畫很簡單,只是一次性的屬性變化。
-
你不想在設計中拖放太多組件。
-
你想保持代碼的簡潔性,避免管理動畫對象的麻煩。
-
動畫是動態觸發的,且參數可能每次都不一樣。
- 當在如下情形時,選擇 TAnimation 組件:
-
動畫是UI設計的重要組成部分,需要在設計時就預覽效果。
-
動畫需要循環播放、自動反轉、或者與其他動畫串聯。
-
你需要精確控制動畫的起始值、結束值。
-
你需要在動畫完成時執行特定的代碼(使用 OnFinish 事件)。
-
同一個動畫會被多次重複使用。
TAnimator提供瞭如下的方法:
- AnimateFloat 方法會隨時間通過特定的插值方式動畫化浮點數屬性值。
- AnimateFloatDelay 方法與 AnimateFloat 方法類似,但它會在開始過程前添加一個初始延遲。
- AnimateInt 方法會隨時間通過特定的插值方式動畫化整數的數值屬性值。
- AnimateColor 方法會隨時間對顏色屬性值進行動畫處理,並使用特定的插值方式。
- AnimateFloatWait 方法與 AnimateFloat 方法類似,但它是同步執行的(方法調用只有在動畫過程結束後才會返回)。
- AnimateIntWait 方法與 AnimateInt 方法類似,但它是同步執行的(方法調用只有在動畫過程結束後才會返回)。
總結
雖然TAnimator非常簡潔,但它封裝了創建、配置、啓動和銷燬動畫對象的全部細節,只給你留下一個最簡單的接口。所以其實滿足很多場景需求。
TAnimation組件適合於創建較為複雜的動畫效果,就比如在《一步一步學習使用FireMonkey動畫(1)》中的案例,你可以在多個動畫組件之間進行協調顯示,這是TAnimator無法實現的。