前言
基本用法
實作原理
在前面實踐元件的開發中,我們做了一個登入的界面,裡面有一個元件Hero,不知道大家是否記得?當時沒有展開來說,是因為它屬于動畫的内容,本文就要重點講解Hero動畫。
做過Java開發Android的程式員應該都清楚,Shared Element Transition可以讓Activity或Fragment做出流暢的動畫,同樣,在Flutter開發中,Hero動畫也能實作類似的效果。簡單來說,Hero的作用就是在路由之間做出流暢的轉場動畫。
Hero元件的用法是需要同時定義源元件和目标元件,其中源元件和目标元件被Hero包裹在需要動畫控制的元件外面,如果有一方不指定,在有些情況下,界面就會卡死,我們先來看看它的基本用法,首先是main.dart代碼:
代碼很簡單,就是監聽點選事件ontap,hero包裹FlutterLogo元件,然後點選跳轉到第二個界面。接着我們再來看看第二個頁面CustomFlutterLogo.dart的代碼:
這段代碼也很簡單,就是常用的元件,隻是在外層套了一層Hero動畫元件,不過這裡有一點我們需要注意,hero裡面有一個tag屬性,必須寫上,不然會報錯,不信的讀者,可以删除後運作試試。
我們基本已經掌握了Hero路由跳轉動畫的用法,但我們不能隻看表面,不明其原理,因為後面講解的動畫也會涉及到這些知識,是以我們必須掌握。
Hero動畫,它的整個運動過程分為3個步驟,即動畫開始(t=0.0),動畫進行中,動畫結束(t=1.0),下面是Hero動畫運動示意圖:
如上圖所示,兩個路由之間還有一個Overlay層。在動畫開始時,Flutter會計算出Hero的位置并複制一份,然後繪制到Overlay層上。複制的Hero和源Hero的大小是一緻的,并且該Hero是在所有路由之上。在動畫實作的過程中,Flutter會逐漸把源Hero移除螢幕。在動畫進行中Flutter是依靠Tween來實作,通過createRectTween屬性把Tween傳給Hero。Hero内部預設使用MeterialRectArcTween的曲線路徑進行移動動畫的操作。在動畫結束時,Flutter将Overlay中的Hero移除,且完成了Hero在目标路由上的顯示,這時Overlay是空白的。
Hero中所有變換都是通過HeroController來實作的,HeroController是在MeterialApp中通過initState和didUpdateWidget方法來完成初始化的,源碼如下所示:
在初始化HeroController時,Flutter攜帶了一個參數,就是_createRectTween,該參數傳回的預設項就是MaterialRectArcTween。Flutter源碼裡還為我們實作了第二種RectTween傳回值,即MaterialRectCenterArcTween。由此可見,可以對createRectTween進行自定義。我們再看看HeroController的具體内容,代碼如下:
HeroController其實繼承的是NavigatorObserver。在路由操作的didPush和didPop回調方法裡,可以調用_maybeStartHeroTransition,并通過WidgetsBinding把源路由,目标路由,HeroController關聯起來。在使用didPush和didPop回調時,通過調用_startHeroTransition方法讓Hero動起來,隻不過前者是正向的,後者是逆向的。