1. 程式人生 > >【Android】屬性動畫(基本用法)

【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變成0ObjectAnimator還支援多個動畫。

  • :在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:下個位置大於上個上個位置時,向下移動,反之向上移動。 如:translationX0f-> -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中的動畫同時執行sequentiallyset中的動畫按順序執行 最後看看效果:

組合動畫

轉載連結:https://www.jianshu.com/p/d23f58f4368d