前言:
這是我參與8月更文挑戰的第 8 天,活動詳情檢視:8月更文挑戰。為應掘金的八月更文挑戰
,我準備在本月挑選 31
個以前沒有介紹過的元件,進行全面分析和屬性介紹。這些文章將來會作為 Flutter 元件集錄
的重要素材。希望可以堅持下去,你的支援將是我最大的動力~
- 1.【Flutter 元件集錄】NotificationListener| 8月更文挑戰
- 2.【Flutter 元件集錄】Dismissible| 8月更文挑戰
- 3.【Flutter 元件集錄】Switch 是怎樣煉成的| 8月更文挑戰
- 4.【Flutter 元件集錄】Scrollbar| 8月更文挑戰
- 5.【Flutter 元件集錄】ClipPath| 8月更文挑戰
- 6.【Flutter 元件集錄】CupertinoActivityIndicator| 8月更文挑戰
- 7.【Flutter 元件集錄】Opacity| 8月更文挑戰
- 8.【Flutter 元件集錄】FadeTransition| 8月更文挑戰
[本文]
一、認識 FadeTransition 元件
上一篇介紹了 Opacity 元件,今天來看一個可以透明動畫變換的元件:
FadeTransition。其作用是:將一個
元件 以指定透明度
opacity 動畫進行
透明變化`。
1.FadeTransition 基本資訊
下面是 FadeTransition
元件類的定義
和 構造方法
,可以看出它繼承自 SingleChildRenderObjectWidget
。例項化時必須傳入 opacity
入參,其型別為 Animation<double>
,用於控制透明度的動畫器。還可以傳入一個 chuild
元件。
---->[FadeTransition#FadeTransition 宣告]----
final Animation<double> opacity;
複製程式碼
2.FadeTransition 的使用
FadeTransition 元件的比 Opacity
複雜很多,因為我們要指定 opacity
動畫器,像這樣由使用者知道動畫器
實現動畫效果的,稱之為 顯示動畫元件
。如下程式碼,是在 2S
內將透明度在 0.2 ~ 1.0
間變換的動畫效果:
由於需要使用 動畫器
,我們需要使用 StatefulWidget
,在 XXXState
中混入 SingleTickerProviderStateMixin
,可以讓狀態類作為 vsync
用來建立 AnimationController
。在 dispose
中釋放動畫控制器。
class FadeTransitionDemo extends StatefulWidget {
@override
_FadeTransitionDemoState createState() => _FadeTransitionDemoState();
}
class _FadeTransitionDemoState extends State<FadeTransitionDemo>
with SingleTickerProviderStateMixin {
late AnimationController _ctrl;
late Animation<double> opacityAnim;
@override
void initState() {
super.initState();
_ctrl = AnimationController(vsync: this, duration: const Duration(seconds: 2));
opacityAnim= Tween<double>(begin: 0.2,end: 1.0).animate(_ctrl);
_ctrl..forward();
}
@override
void dispose() {
_ctrl.dispose();
super.dispose();
}
複製程式碼
通過 Tween
和 _ctrl
建立一個 0.2 ~ 1.0
的動畫器 opacityAnim
, 作為入參傳入 FadeTransition
建構函式中。這樣在 _ctrl
動畫控制器開啟時,其子元件就可以執行透明度漸變動畫。
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
_ctrl.forward(from: 0);
},
child: FadeTransition(
opacity: opacityAnim,
child: Image.asset(
'assets/images/icon_head.png',
width: 100,
height: 100,
),
),
);
}
複製程式碼
二、 FadeTransition 的原始碼實現
1. FadeTransition 原始碼分析
它繼承自 SingleChildRenderObjectWidget
就說明,該元件需要維護一個 RenderObject
物件的建立及更新。
在 createRenderObject
方法中,建立 RenderAnimatedOpacity
,opacity
動畫器會被傳如構造入參中。在 updateRenderObject
中,對 RenderAnimatedOpacity
物件進行更新。也就是說,漸變透明變換的繪製處理是在 RenderAnimatedOpacity
中進行的。
2.RenderAnimatedOpacity 原始碼分析
對於 FadeTransition
元件來說,最神奇的應該是:為什麼透明度會跟隨 Animation
物件不斷觸發重繪,從而進行動畫。既然 動畫器 opacity
是一個 Listenable
物件,那很容易想到是通過監聽 動畫器
進行重繪。
RenderAnimatedOpacity
通過混入 RenderAnimatedOpacityMixin
實現動畫效果。
在 RenderAnimatedOpacityMixin#attach
方法中,會通過 addListener
來監聽動畫器的變化。在 detach
中移除監聽。監聽的方法是 _updateOpacity
。
在 _updateOpacity
方法中,如果新舊的 alpha
值不同,就會觸發 markNeedsPaint
進行通知重繪。
在 RenderAnimatedOpacityMixin#paint
方法中的繪製邏輯和 Opacity
元件繪製是一樣的。當 child
非空時,如果 _alpha = 0
就什麼都不需要畫,直接返回。如果 _alpha = 255
,則直接繪製 child
。
如果有透明度時,會通過 context.pushOpacity
,建立一個透明層 layer
來完成透明功能。該方法在 Opacity 元件一文中介紹過了,這裡不再贅述。
3. FadeTransition 的價值
如果不知道 FadeTransition
元件的存在,我們想要實現 透明度漸變
的效果,能想到的可能就是通過 AnimatedBuilder
監聽 Opacity
元件,來動態改變透明度值,完成動畫,程式碼如下:
AnimatedBuilder(
animation: opacityAnim,
builder: (ctx, child) => Opacity(
opacity: opacityAnim.value,
child: child,
),
child: Image.asset(
'assets/images/icon_head.png',
width: 100,
height: 100,
),
),
複製程式碼
上面的方式可以達到一樣的效果,那這和 FadeTransition
想必有什麼劣勢呢?首先,很明顯使用 AnimatedBuilder
元件比較麻煩;其次使用 AnimatedBuilder
元件,每次動畫器數值變化都會執行 builder
回撥來建立元件,也就是說 Opacity
元件會被建立很多次。
而從 FadeTransition
原始碼中可以看出,對動畫器的監聽是在其對應的 RenderAnimatedOpacity
中進行的,也就是說,通過 FadeTransition
元件進行 透明度漸變動畫
的整個動畫過程,是沒有伴隨任何元件重建的。這就是其最大的優勢。
FadeTransition 元件
的使用方式到這裡就介紹完畢,那本文到這裡就結束了,謝謝觀看,明天見~