【Android】屬性動畫(基本用法)
1、前言
在我們體驗一款APP時,炫酷的動畫往往能讓使用者體驗大幅度提升。想當年我剛學Android
的時候,無意中看到蘑菇街購物車的動畫效果,把我給激動得,非要在自己的APP中加入那動畫,記得當時用費了好大的勁...不提了,說多了都是淚...
先了解下,目前可以實現動畫的方式有:
- 幀動畫(
Frame
) :將一個完整的動畫拆分成一張張單獨的圖片,然後再將它們連貫起來進行播放特點:幀動畫 由於是一幀一幀的,所以需要圖片多。會增大apk的大小,但是這種動畫可以實現一些比較難的效果 比如說等待的環形進度 - 補間動畫(
Tween
) 慢慢過渡,設定初值和末值,並用插值器來控制過渡特點:相對也比較簡單,頁面切換的動畫多用這個來做。缺點,視覺上 上變化,並不是真正的位置上的變化。 - 屬性動畫(
Property
) 控制屬性來實現動畫。特點:最為強大的動畫,彌補了補間動畫的缺點,實現位置+視覺的變化。並且可以自定義插值器,實現各種效果
2、實現(Java)
我想,與其看文字介紹還不如直接看效果和程式碼。先來個組合的動畫效果。
組合動畫
雖然不是很炫酷,不過這個效果包含多個基本動畫。老規矩,從基礎的開始一點一點來。
這裡主要介紹ObjectAnimator
的用法。
2.1、透明度
剛剛演示的效果中,一開始有個變透明的過程,來看看單純的變透明怎麼寫。
透明度由0~1表示。0表示完全透明,1表示不透明
- 例:在1s內,將
imageView
的透明度從1
變成0
。
//透明度起始為1,結束時為0
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0f);
animator.setDuration(1000);//時間1s
animator.start();
ofFloat
中的引數:imageView
:執行動畫的View
;"alpha"
:表示透明動畫;1f
:起始透明度;0f
:動畫結束後的透明度;
還可以省略1f
,寫成下面這樣
(注:只有執行一次動畫的時候才可以這麼寫。這麼說還可以執行多次?不急,往下看~~)
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 0f);
效果:
alpha
從效果可以看出,動畫完成後,imageView
就直接變透明瞭,回都回不來。從這也能猜出,屬性動畫直接改變了檢視的屬性。
除了把透明度從1
變成0
,ObjectAnimator
還支援多個動畫。
- 例:在2s內,將
imageView
的透明度從1
變成0
然後再變成1
。
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0f, 1f);
animator.setDuration(2000);
animator.start();
這裡只要多加個引數,表示下一次動畫。 效果:
alpha
這裡執行了兩次動畫,可以看出,2s的時間平均分配給了這兩次動畫。如果你想執行三次、四次...動畫,只要在後面多加幾個引數就可以了。這也適用於其他的幾個動畫效果:旋轉、移動、縮放
如果你想讓它一直重複的話,可以使用
ObjectAnimator
提供的setRepeatCount(int count)
。count
為重複次數,-1
表示一直重複。
animator.setRepeatCount(-1);
2.2、旋轉
- 例:在2s內,順時針旋轉360度,然後再逆時針旋轉360度。
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f, 0f);
animator.setDuration(2000);
animator.start();
效果:
rotation
注:
下個度數大於上個度數,順時針旋轉;下個度數小於上個度數,逆時針旋轉。
如:0f
-> 360f
,順時針; 360f
-> 0f
,逆時針。
2.3、移動
- 例:在2s內,沿x軸左移300個畫素,然後再右移300個畫素
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "translationX", 0f, -300f, 0f);
animator.setDuration(2000);
animator.start();
效果:
translationX
這裡的移動分為沿x、y
軸移動,沿x軸時使用translationX
,沿y
軸移動使用translationY
。注:
translationX:下個位置大於上個上個位置時,向右移動,反之向左移動;
translationY:下個位置大於上個上個位置時,向下移動,反之向上移動。
如:translationX
:0f
-> -300f
,向左;-300f
-> 0f
,向右。
2.4、縮放
例:在2s內,沿x軸放大成原來的兩倍,然後縮小會原樣。
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 2f, 1f);
animator.setDuration(2000);
animator.start();
效果:
scaleX
縮放和移動相似,也分為沿x、y
軸來放縮。沿x軸縮放使用scaleX
,沿y
軸縮放使用scaleY
。注:
後面的引數表示倍數,1f表示原來的大小,以此推類:2f表示兩倍、3f表示三倍
如:1f
-> 2f
,放大成原來的兩倍;2f
-> 1f
,從兩倍變為原樣。
2.5組合動畫
如果只有這些基本動畫是無法滿足我們實際的應用的,所以還有個類AnimatorSet
,專門來組合這些動畫。AnimatorSet
:這個類提供了一個play()方法,呼叫後將會返回一個AnimatorSet.Builder
的例項,AnimatorSet.Builder
中包括以下四個方法:
after(Animator anim)
:將現有動畫插入到傳入的動畫之後執行after(long delay)
:將現有動畫延遲指定毫秒後執行before(Animator anim)
: 將現有動畫插入到傳入的動畫之前執行with(Animator anim)
:將現有動畫和傳入的動畫同時執行
接下來看看應該怎麼使用。例:在3s內,沿x、y
軸同時放大,然後縮小,在縮放的同時還要改變透明度。然後再完成3s的左右移動。
//沿x軸放大
ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 2f, 1f);
//沿y軸放大
ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(imageView, "scaleY", 1f, 2f, 1f);
//移動
ObjectAnimator translationXAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 0f, 200f, 0f);
//透明動畫
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0f, 1f);
AnimatorSet set = new AnimatorSet();
//同時沿X,Y軸放大,且改變透明度,然後移動
set.play(scaleXAnimator).with(scaleYAnimator).with(animator).before(translationXAnimator);
//都設定3s,也可以為每個單獨設定
set.setDuration(3000);
set.start();
效果:
組合動畫
也可以設定延遲執行
animator.setStartDelay(1000);//延遲1000ms後執行,需要在start()前呼叫
2.6、監聽事件
在動畫執行前,還可以為動畫新增監聽事件。
//新增監聽事件
set.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
//動畫開始的時候呼叫
}
@Override
public void onAnimationEnd(Animator animation) {
//畫結束的時候呼叫
}
@Override
public void onAnimationCancel(Animator animation) {
//動畫被取消的時候呼叫
}
@Override
public void onAnimationRepeat(Animator animation) {
//動畫重複執行的時候呼叫
}
});
這樣是不是太費事了?有時候,我們只想監聽其中的某個事件,其他的我們並不關心。官方還是很人性化得為我們提供了另一個類:AnimatorListenerAdapter
,在這個類中,只要重寫我們想要的監聽事件就可以了。
//另一種設定監聽的方式,裡面的監聽方法可以選擇性重寫
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
}
});
3、實現(XML)
不僅可以在Java程式碼中實現屬性動畫,屬性動畫和過去的補間動畫一樣,都可以在XML中編寫。在XML中編寫好,在某些情況下還能重用。
首先要在res
下建立一個animator
資料夾
注意:是
animator
,不是anim
在XML
中:ObjectAnimator
——> <objectAnimator>
AnimatorSet
——> <set>
3.1、透明度
例:2s內,透明度從0.5f
變為1f
,且一直重複動畫,重複模式為reverse
- 在
animator
資料夾下,建立alpha.xml
檔案:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:propertyName="alpha"
android:repeatCount="-1"
android:repeatMode="reverse"
android:valueFrom="0.5"
android:valueTo="1"
android:valueType="floatType" />
android:duration
:動畫持續時間;android:propertyName
:動畫型別;android:repeatCount
:重複次數,-1為一直重複;android:repeatMode
:重複模式:reverse
(從結束的位置繼續), restart
(從新開始);android:valueFrom
:起始值;android:valueTo
:結束值。android:valueType
:值型別
- 在Java中呼叫:
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.alpha);
animator.setTarget(imageView);
animator.start();
這樣就能實現之前的透明效果,圖片我就不貼了
3.2、旋轉
例:在2s內,順時針旋轉360度
- 在
animator
資料夾下,建立rotation.xml
檔案:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="0"
android:valueTo="360"
android:duration="2000"
android:propertyName="rotation"
android:valueType="floatType"/>
這裡就將android:propertyName
的值改為rotation
- 在Java中的呼叫跟上面的相似。
3.3、移動
例:在2s內,沿x軸向右移動200px
- 在
animator
資料夾下,建立translation_x.xml
檔案:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:propertyName="translationX"
android:repeatCount="-1"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="200"
android:valueType="floatType"/>
這裡就將android:propertyName
的值改為translationX
,若沿y
軸,使用translationY
即可。
- 在Java中的呼叫跟上面的相似。
3.4、縮放
例:在2s內,沿x軸放大成1.5倍
- 在
animator
資料夾下,建立scale_x.xml
檔案:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:propertyName="scaleX"
android:valueFrom="1"
android:valueTo="1.5"
android:valueType="floatType" />
這裡就將android:propertyName
的值改為scaleX
,若沿y
軸,使用scaleY
即可。
- 在Java中的呼叫跟上面的相似。
3.5、組合動畫
例:完成這樣的移動動畫效果:向左移動並旋轉,然後回到原來的位置,接著向右移動並旋轉,然後回到原來的位置。效果如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially">
<set>
<objectAnimator
android:duration="4000"
android:propertyName="rotation"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="360" />
<set android:ordering="sequentially">
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="200" />
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:repeatMode="reverse"
android:valueFrom="200"
android:valueTo="0" />
</set>
</set>
<set >
<objectAnimator
android:duration="4000"
android:propertyName="rotation"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="360" />
<set android:ordering="sequentially">
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="-200" />
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:repeatMode="reverse"
android:valueFrom="-200"
android:valueTo="0" />
</set>
</set>
</set>
這裡需要說下set
中的屬性android:ordering
:規定了這個set
中的動畫的執行順序,包括:together
(預設):set
中的動畫同時執行sequentially
:set
中的動畫按順序執行
最後看看效果:
組合動畫
轉載連結:https://www.jianshu.com/p/d23f58f4368d