【有夢想的IT人】Android-動畫的入門和實現(xiàn)

在我們Android開發(fā)中,經(jīng)常會使用到簡單或者動畫,這里就對Android開發(fā)中的動畫做了一下簡單的總結(jié)。

Android 動畫分類

總的來說,Android動畫可以分為兩類,最初的傳統(tǒng)動畫和Android3.0 之后出現(xiàn)的屬性動畫;
傳統(tǒng)動畫又包括 幀動畫(Frame Animation)補(bǔ)間動畫(Tweened Animation)

Paste_Image.png

一傳統(tǒng)動畫

1.幀動畫

幀動畫是最容易實現(xiàn)的一種動畫,這種動畫更多的依賴于完善的UI資源,他的原理就是將一張張單獨的圖片連貫的進(jìn)行播放,
從而在視覺上產(chǎn)生一種動畫的效果;而我們要做的就是:使用代碼把一幅幅的圖片按順序顯示。


我們來寫上面逗比貓的動畫:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@drawable/a_0"
        android:duration="100" />
    <item
        android:drawable="@drawable/a_1"
        android:duration="100" />
    <item
        android:drawable="@drawable/a_2"
        android:duration="100" />
</animation-list>  
protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_frame_animation);
        ImageView animationImg1 = (ImageView) findViewById(R.id.animation1);
        animationImg1.setImageResource(R.drawable.frame_anim1);
        AnimationDrawable animationDrawable1 = (AnimationDrawable) animationImg1.getDrawable();
        animationDrawable1.start();
    }

在有些代碼中,我們還會看到android:oneshot="false" ,這個oneshot 的含義就是動畫執(zhí)行一次(true)還是循環(huán)執(zhí)行多次。

上面其他幾個動畫實現(xiàn)方式都是一樣,無非就是圖片資源的差異。(其實我們小時看過的動畫片大部分就是這樣搞出來的)

2.補(bǔ)間動畫

補(bǔ)間動畫又可以分為四種形式,分別是** alpha(淡入淡出),translate(位移),scale(縮放大?。?strong>,rotate(旋轉(zhuǎn))**。
補(bǔ)間動畫的實現(xiàn),一般會采用xml 文件的形式;代碼會更容易書寫和閱讀,同時也更容易復(fù)用。

XML 實現(xiàn)

首先,在res/anim/ 文件夾下定義如下的動畫實現(xiàn)方式

alpha_anim.xml 動畫實現(xiàn)
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromAlpha="1.0"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:toAlpha="0.0" />
scale.xml 動畫實現(xiàn)
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromXScale="0.0"
    android:fromYScale="0.0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toXScale="1.0"
    android:toYScale="1.0"/>
然后,在Activity中
Animation animation = AnimationUtils.loadAnimation(mContext, R.anim.alpha_anim);
img = (ImageView) findViewById(R.id.img);
img.startAnimation(animation);

這樣就可以實現(xiàn)ImageView alpha 透明變化的動畫效果。

也可以使用set 標(biāo)簽將多個動畫組合(代碼源自Android SDK API)

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:shareInterpolator=["true" | "false"] >
    <alpha
        android:fromAlpha="float"
        android:toAlpha="float" />
    <scale
        android:fromXScale="float"
        android:toXScale="float"
        android:fromYScale="float"
        android:toYScale="float"
        android:pivotX="float"
        android:pivotY="float" />
    <translate
        android:fromXDelta="float"
        android:toXDelta="float"
        android:fromYDelta="float"
        android:toYDelta="float" />
    <rotate
        android:fromDegrees="float"
        android:toDegrees="float"
        android:pivotX="float"
        android:pivotY="float" />
    <set>
        ...
    </set>
</set>

可以看到組合動畫是可以嵌套使用的。
各個動畫屬性的含義結(jié)合動畫自身的特點應(yīng)該很好理解,就不一一闡述了;這里主要說一下interpolatorpivot。
Interpolator 主要作用是可以控制動畫的變化速率 ,就是動畫進(jìn)行的快慢節(jié)奏。

Android 系統(tǒng)已經(jīng)為我們提供了一些Interpolator ,比如 accelerate_decelerate_interpolator,accelerate_interpolator等。更多的interpolator 及其含義可以在Android SDK 中查看。同時這個Interpolator也是可以自定義的,這個后面還會提到。
pivot 決定了當(dāng)前動畫執(zhí)行的參考位置

pivot 這個屬性主要是在translate 和 scale 動畫中,這兩種動畫都牽扯到view 的“物理位置“發(fā)生變化,所以需要一個參考點。而pivotX和pivotY就共同決定了這個點;它的值可以是float或者是百分比數(shù)值。
我們以pivotX為例,

pivotX取值 含義
10 距離動畫所在view自身左邊緣10像素
10% 距離動畫所在view自身左邊緣 的距離是整個view寬度的10%
10%p 距離動畫所在view父控件左邊緣的距離是整個view寬度的10%

pivotY 也是相同的原理,只不過變成的縱向的位置。如果還是不明白可以參考源碼,在Tweened Animation中結(jié)合seekbar的滑動觀察rotate的變化理解。

使用代碼實現(xiàn)

有時候,動畫的屬性值可能需要動態(tài)的調(diào)整,這個時候使用xml 就不合適了,需要使用代碼實現(xiàn)

private void RotateAnimation() {
        animation = new RotateAnimation(-deValue, deValue, Animation.RELATIVE_TO_SELF,
                pxValue, Animation.RELATIVE_TO_SELF, pyValue);
        animation.setDuration(timeValue);

        if (keep.isChecked()) {
            animation.setFillAfter(true);
        } else {
            animation.setFillAfter(false);
        }
        if (loop.isChecked()) {
            animation.setRepeatCount(-1);
        } else {
            animation.setRepeatCount(0);
        }

        if (reverse.isChecked()) {
            animation.setRepeatMode(Animation.REVERSE);
        } else {
            animation.setRepeatMode(Animation.RESTART);
        }
        img.startAnimation(animation);
    }

這里animation.setFillAfter決定了動畫在播放結(jié)束時是否保持最終的狀態(tài);animation.setRepeatCount和animation.setRepeatMode 決定了動畫的重復(fù)次數(shù)及重復(fù)方式,具體細(xì)節(jié)可查看源碼理解。

好了,傳統(tǒng)動畫的內(nèi)容就說到這里了,個人覺得傳統(tǒng)動畫真的是被時代的潮流推得很靠后了。

二.屬性動畫

屬性動畫是現(xiàn)在使用的最多的一種動畫,顧名思義它是對于對象屬性的動畫。它比補(bǔ)間動畫更加強(qiáng)大,所有補(bǔ)間動畫的內(nèi)容,都可以通過屬性動畫實現(xiàn)。

屬性動畫大致分為兩種類型ViewPropertyAnimatorObjectAnimator。
ViewPropertyAnimator:適合一些通用的動畫,比如旋轉(zhuǎn)、位移、縮放和透明,使用方式也很簡單通過View.animate()即可得到ViewPropertyAnimator,之后進(jìn)行相應(yīng)的動畫操作即可。
ObjectAnimator:適合用于為我們的自定義控件添加動畫,當(dāng)然首先我們應(yīng)該在自定義View中添加相應(yīng)的getXXX()和setXXX()相應(yīng)屬性的getter和setter方法,這里需要注意的是在setter方法內(nèi)改變了自定義View中的屬性后要調(diào)用invalidate()來刷新View的繪制。之后調(diào)用ObjectAnimator.of屬性類型()返回一個ObjectAnimator,調(diào)用start()方法啟動動畫即可。

屬性動畫入門

首先我們來看看如何用屬性動畫實現(xiàn)上面補(bǔ)間動畫的效果

private void RotateAnimation() {
    ObjectAnimator anim = ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
    anim.setDuration(1000);
    anim.start();
}

private void AlpahAnimation() {
    ObjectAnimator anim = ObjectAnimator.ofFloat(myView, "alpha", 1.0f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f);
    anim.setRepeatCount(-1);
    anim.setRepeatMode(ObjectAnimator.REVERSE);
    anim.setDuration(2000);
    anim.start();
}

這兩個方法用屬性動畫的方式分別實現(xiàn)了旋轉(zhuǎn)動畫和淡入淡出動畫,其中setDuration、setRepeatModesetRepeatCount和補(bǔ)間動畫中的概念是一樣的。

可以看到,屬性動畫貌似強(qiáng)大了許多,實現(xiàn)很方便,同時動畫可變化的值也有了更多的選擇,動畫所能呈現(xiàn)的細(xì)節(jié)也更多。

當(dāng)然一樣牛逼的是屬性動畫也是可以組合實現(xiàn)

                ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(myView, "alpha", 1.0f, 0.5f, 0.8f, 1.0f);
                ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(myView, "scaleX", 0.0f, 1.0f);
                ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(myView, "scaleY", 0.0f, 2.0f);
                ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(myView, "rotation", 0, 360);
                ObjectAnimator transXAnim = ObjectAnimator.ofFloat(myView, "translationX", 100, 400);
                ObjectAnimator transYAnim = ObjectAnimator.ofFloat(myView, "tranlsationY", 100, 750);
                AnimatorSet set = new AnimatorSet();
                set.playTogether(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
//                set.playSequentially(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
                set.setDuration(3000);
                set.start();

可以看到這些動畫可以同時播放,或者是按序播放。
動畫監(jiān)聽器

您可以在動畫持續(xù)時間期間使用下面描述的偵聽器偵聽重要事件。

  • Animator.AnimatorListener

  • onAnimationStart() - 動畫啟動時調(diào)用。
  • onAnimationEnd() - 當(dāng)動畫結(jié)束時調(diào)用。
  • onAnimationRepeat() - 當(dāng)動畫重演調(diào)用
  • onAnimationCancel()-當(dāng)動畫被取消調(diào)用。取消的動畫還呼吁onAnimationEnd(),無論他們是如何結(jié)束。
  • ValueAnimator.AnimatorUpdateListener

  • onAnimationUpdate()-稱為動畫的每一幀上。 聽此事件使用所產(chǎn)生的計算值ValueAnimator動畫中。 要使用該值,查詢ValueAnimator傳遞到事件來獲取與當(dāng)前動畫值對象getAnimatedValue()方法。 實現(xiàn)這個監(jiān)聽器。

根據(jù)什么屬性或?qū)ο蟮膭赢嫞憧赡苄枰{(diào)用invalidate()上查看迫使屏幕的該區(qū)域的新的動畫值重繪自身。 例如,對Drawable對象的顏色屬性進(jìn)行動畫處理只會在該對象重繪本身時更新屏幕。 所有在查看屬性制定者,如setAlpha()和setTranslationX()正確無效視圖,所以你不需要調(diào)用這些方法與新的值時無效視圖。

在XML聲明動畫

屬性動畫系統(tǒng)允許您使用XML聲明屬性動畫,而不是以編程方式。 通過在XML中定義動畫,您可以輕松地在多個活動中重復(fù)使用動畫,并更輕松地編輯動畫序列。

為了區(qū)分使用與那些使用舊的新的屬性動畫的API動畫文件觀看動畫框架,開始與Android 3.1,你應(yīng)該保存XML文件在屬性動畫res/animator/目錄下。

以下屬性動畫類通過以下XML標(biāo)記支持XML聲明:
ValueAnimator - <animator>
ObjectAnimator - <objectAnimator>
AnimatorSet - <set>
下面的示例播放兩套對象的動畫順序,第一組嵌套組一起編寫兩個對象的動畫:
<set android:ordering="sequentially">
  <set>
      <objectAnimator
          android:propertyName="x"
          android:duration="500"
          android:valueTo="400"
          android:valueType="intType"/>
      <objectAnimator
          android:propertyName="y"
          android:duration="500"
          android:valueTo="300"
          android:valueType="intType"/>
  </set>
  <objectAnimator
      android:propertyName="alpha"
      android:duration="500"
      android:valueTo="1f"/>
</set>

為了運(yùn)行這個動畫,必須在代碼中的充氣XML資源AnimatorSet對象,然后開始動畫集之前為所有動畫的目標(biāo)對象。呼叫setTarget()設(shè)置的所有兒童的單一目標(biāo)對象AnimatorSet的方便。下面的代碼演示如何做到這一點:

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
  R.anim.property_animator);
set.setTarget(myObject);
set.start();

當(dāng)然了,關(guān)于動畫已經(jīng)有好多NB的開源動畫庫了例如Lottie動畫庫,Facebook-Rebound 彈性動畫庫

本文參考鏈接:http://www.itdecent.cn/p/420629118c10

嗨~我是夏尼采,一個有夢想的IT
每周輸出1篇有用的文章。
如果文章對您有幫助,希望能點個贊或者關(guān)注我。
您的關(guān)注和點贊是對我最大的鼓勵,感謝您的閱讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容