flutter動畫中有4個比較重要的角色:animation、controller、curve、tween,先來了解一下這四個角色
animation是flutter動畫庫中的核心類,用于插入指導動畫的值
animation對象知道動畫目前的狀态(比如開始還是停止),可以使用addlistener和addstatuslistener監聽動畫狀态改變。
addlistener: 每一幀都會調用,調用之後一般使用setstate來重新整理界面
addstatuslistener:監聽動畫目前的狀态 如動畫開始、結束、正向或反向
在flutter中,animation對象本身和ui渲染沒有任何關系。animation是一個抽象類,它擁有其目前值和狀态(完成或停止)。其中一個比較常用的animation類是 animation<double> ,還可以生成除double之外的其他類型值,如: animation<color> 或 animation<size> 。
用來管理animation,它繼承自animation, 是個特殊的animation ,螢幕每重新整理一幀,它都會生成一個新值,需要一個vsync參數, vsync的存在可以防止背景動畫消耗不必要的資源 。
vsync的值怎麼獲得,可以讓stateful對象擴充使用tickerproviderstatemixin比如:
animationcontroller在預設情況下,在給定的時間段内,animationcontroller會生成0.0到1.0的數字。
它可以控制動畫,比如使用 .forward() 方法可以啟動一個動畫, .stop() 可以結束一個動畫, .reverse() 啟動反向動畫。
看一下animationcontroller的構造方法,有一個必須的參數tickerprovider,就是前面給定的tickerproviderstatemixin
在statefulwidget中建立一個animationcontroller對象
定義動畫曲線,運動過程,比如勻速,先加速在減速等等
它有兩個必要的參數parent和curve。parent就是前面的animationcontroller對象,curve就是動畫運作的曲線,相當于android屬性動畫中的插值器curve都有哪些取值呢
linear|勻速的
decelerate|勻減速
ease|先加速後減速
easein|開始慢後面快
easeout|開始快後面慢
easeinout|先慢在快在慢
上面是常用的一些曲線,還有很多中曲線運動的方式可以去curve.dart源碼中去看,源碼注釋中有mp4的連結,可以清楚的看到動畫運動的視訊。
如果系統提供的運動曲線仍然無法滿足我們的需求,那就可以繼承curve來自己實作一個。上面的代碼可以看到curve是一個抽象類,繼承它并重寫transform方法即可。比如我們可以自己在裡面實作一個sin或者cos函數的曲線。例如
建立一個curvedanimation對象
給動畫對象插入一個範圍值
預設情況下,animationcontroller對象的範圍從0.0到1.0,如果我們想要更大的範圍,就需要使用到tween了。比如
class tween<t extends dynamic> extends animatable<t> tween繼承自animatable,接收一個begin和一個end值,tween的職責就是定義從輸入範圍到輸出範圍的映射。是以這兩個值必須能進行加減乘的運算。
要使用tween對象,調用其animate()方法,傳入一個控制器對象,傳回一個animation對象。例如,
動畫的四個角色都了解了,下面開始使用這些角色來建構一個動畫,動畫效果如下圖
有一個心形的button,點選的時候放大并且顔色漸變,在點選的時候原路傳回
2.1中每次寫動畫都需要在addlistener中設定setstate來更新ui,有點麻煩,系統給提供了一個animatedwidget,它内部封裝了addlistener和setstate的邏輯,我們隻需要傳給它animationcontroller和animation就行了。
而且我們可以自定義一個widget繼承它,讓動畫跟原來的視圖代碼分離
自定義一個animationheart繼承自animatedwidget,在構造方法中将animationcontroller和animation傳過來。其餘的跟2.1中一樣,最終效果也一樣。
flutter中還可以使用animatedbuilder來建構一個動畫
執行個體化四個動畫元素的代碼跟前面還是一樣,主要是在build代碼塊中使用animatedbuilder建構,傳入animation對象。看起來比2.2中的方式也沒有簡單多少,不過看一下它的構造方法,系統還給提供了一個可選的參數child,讓它天然就支援封裝。
必需要一個listenable,animation就是listenable
必需要一個builder,前面的代碼中知道builder中需要傳一個context和一個child
可以傳一個child。 傳入的這個child最終會傳入到builder中
上面的例子中我們是直接在builder中建立了一個控件,既然child可以傳進來,那麼我們可以把一個類型的動畫封裝一下比如縮放動畫,漸變動畫等,以後隻要把需要此動畫的小部件傳進來,這個小部件就有這個動畫了。
比如下面定義一個可以縮放的小部件。
hero動畫很簡單不過在平時的項目中也經常用到,主要用在路由頁面之間切換。比如一個頭像點選看大圖,或者新聞清單頁面,點選看詳情,這種共享式的無縫切換。
動畫效果如下圖
目前頁面的圓形小圖和詳情頁面的大圖都使用hero包裹。
必須使用相同的tag,flutter framework通過tag來确定他們之間的關系。
有時候我們需要實作一組複雜的動畫,比如在0.1-0.2秒縮放,從0.2-0.4秒顔色漸變,從0.4-0.8秒左右移動,這時候使用交織動畫可以友善的完成,使用交織動畫需要注意下面幾點
需要使用多個animation對象
一個animationcontroller控制所有的動畫對象
給每一個動畫對象指定時間間隔(interval)
staggeranimation中定義了5個動畫,寬,高,顔色,左邊距,圓角
使用interval來定義某個動畫執行的時機
最後異步啟動動畫。