Android四大動(dòng)畫

前言

動(dòng)畫是生活中必不可少的東西,只要在向用戶傳遞信息或展示內(nèi)容都會(huì)用到動(dòng)畫,接下來我們講講在 Android 中的一些動(dòng)畫,這些動(dòng)畫主要分為 4 種,分別是 幀動(dòng)畫, 矢量動(dòng)畫, 補(bǔ)間動(dòng)畫, 屬性動(dòng)畫。

一.幀動(dòng)畫

幀動(dòng)畫,顧名思義就是通過一張張圖片通過快速切換而到達(dá)的一種視覺效果,看起來像圖片中的物體動(dòng)起來一般,我們平常說的 60幀,120幀,指的就是一秒鐘播放 60張圖片或 120 張圖片。

1.在xml文件中添加圖片

res -> drawable 下面將這一系列連續(xù)的圖片加入進(jìn)去。然后新建一個(gè)名為 fire_animationxml 文件,在文件中給每個(gè) item 添加圖片資源和顯示時(shí)長(zhǎng),如下:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/campfire01" android:duration="80"/>
    <item android:drawable="@drawable/campfire02" android:duration="80"/>
    <item android:drawable="@drawable/campfire03" android:duration="80"/>
    <item android:drawable="@drawable/campfire04" android:duration="80"/>
    <item android:drawable="@drawable/campfire05" android:duration="80"/>
    <item android:drawable="@drawable/campfire06" android:duration="80"/>
    <item android:drawable="@drawable/campfire07" android:duration="80"/>
    <item android:drawable="@drawable/campfire08" android:duration="80"/>
    <item android:drawable="@drawable/campfire09" android:duration="80"/>
    <item android:drawable="@drawable/campfire10" android:duration="80"/>
    <item android:drawable="@drawable/campfire11" android:duration="80"/>
    <item android:drawable="@drawable/campfire12" android:duration="80"/>
    <item android:drawable="@drawable/campfire13" android:duration="80"/>
    <item android:drawable="@drawable/campfire14" android:duration="80"/>
    <item android:drawable="@drawable/campfire15" android:duration="80"/>
    <item android:drawable="@drawable/campfire16" android:duration="80"/>
    <item android:drawable="@drawable/campfire17" android:duration="80"/>
</animation-list>

注意: 根節(jié)點(diǎn)如果是 set 的話,是不能循環(huán)動(dòng)畫的,只能播放一次就結(jié)束

2.activity中使用

接下來在 acctivity_main 中使用這個(gè)資源文件 fire_animation.xml。最后在代碼中解析成 AnimationDrawable,使用就可以了。

v = findViewById(R.id.imageView)
animation = v.drawable as AnimationDrawable
animation.start()

效果如下:


當(dāng)然,這也可以完全通過代碼創(chuàng)建,

v = findViewById(R.id.imageView)

fun fireAnimation() {
       val firesArray = arrayOf(
            R.drawable.campfire01,
            R.drawable.campfire02,
            R.drawable.campfire03,
            R.drawable.campfire04,
            R.drawable.campfire05,
            R.drawable.campfire06,
            R.drawable.campfire07,
            R.drawable.campfire08,
            R.drawable.campfire09,
            R.drawable.campfire10,
            R.drawable.campfire11,
            R.drawable.campfire12,
            R.drawable.campfire13,
            R.drawable.campfire14,
            R.drawable.campfire15,
            R.drawable.campfire16,
            R.drawable.campfire17
        )
        AnimationDrawable().apply {
            //添加圖片資源
            for (item in firesArray) {
                addFrame(getDrawable(item)!!,80)
            }
            //關(guān)聯(lián)圖片和幀動(dòng)畫
            v.setImageDrawable(this)
            //啟動(dòng)
            start()
        }
    }

二.矢量動(dòng)畫

矢量動(dòng)畫相較幀動(dòng)畫就稍顯復(fù)雜,我們來講講使用矢量動(dòng)畫最簡(jiǎn)單的步驟吧。我們通過相關(guān)網(wǎng)站,進(jìn)行動(dòng)畫設(shè)計(jì),它會(huì)為我們快速生成 xml 文件,你可以選擇導(dǎo)入圖片的格式: SVG, Android Drawable

屏幕右邊的方框中,很多值都對(duì)應(yīng)著代碼中的值,上手相對(duì)容易,具體使用請(qǐng)自行百度.

設(shè)計(jì)完矢量動(dòng)畫之后,我們點(diǎn)擊 Export 選擇 Animated Vector Drawable,它會(huì)自動(dòng)為我們生成 xml 文件,之后我們將其添加至 drawable 文件夾中。

<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt">
    <aapt:attr name="android:drawable">
        <vector
            android:name="vector"
            android:width="447dp"
            android:height="285dp"
            android:viewportWidth="447"
            android:viewportHeight="285">
            <path
                android:name="path"
                android:pathData="M 0.307 165.05 L 154.691 285.204 L 446.691 0.358"
                android:strokeColor="#00aa00"
                android:strokeWidth="20"
                android:strokeLineCap="round"
                android:strokeLineJoin="round"/>
        </vector>
    </aapt:attr>
    <target android:name="path">
        <aapt:attr name="android:animation">
            <objectAnimator
                android:propertyName="trimPathEnd"
                android:duration="500"
                android:valueFrom="0"
                android:valueTo="1"
                android:valueType="floatType"
                android:interpolator="@android:interpolator/fast_out_slow_in"/>
        </aapt:attr>
    </target>
</animated-vector>

我們可以看到這個(gè)矢量動(dòng)畫的 xml 是這樣的。那么接下來就是在代碼中將其轉(zhuǎn)化為 AnimatedVectorDrawable 類型(注意在布局中要將srcCompat換成當(dāng)前的資源),這個(gè)和幀動(dòng)畫的使用非常相似。

v = findViewById(R.id.imageView)
val anim = v.drawable as AnimatedVectorDrawable
anim.start()

矢量動(dòng)畫主要麻煩在動(dòng)畫資源文件的書寫,但是我們可以通過這個(gè)網(wǎng)站來快速獲得你預(yù)想動(dòng)畫的代碼,這個(gè)使用起來也是蠻簡(jiǎn)單的。

三.補(bǔ)間動(dòng)畫

補(bǔ)間動(dòng)畫也是蠻特殊的,控件在做動(dòng)畫時(shí),它的位置其實(shí)還是停留在原處,因此如果想在動(dòng)畫結(jié)束后給控件加點(diǎn)擊事件,這樣做是無效的,你需要通過我們待會(huì)要講的屬性動(dòng)畫來完成,但補(bǔ)間動(dòng)畫也有優(yōu)點(diǎn),就是制作簡(jiǎn)便,占用內(nèi)存小等。

屬性 解釋
duration 動(dòng)畫時(shí)長(zhǎng),單位是毫秒
interpolator 動(dòng)畫的播放模式,如勻速
repeatCount 動(dòng)畫播放次數(shù)
repeatMode 設(shè)置動(dòng)畫結(jié)束重新播放動(dòng)畫還是倒放動(dòng)畫
start() 啟動(dòng)動(dòng)畫
cancel() 取消動(dòng)畫
fillBefore 動(dòng)畫播放結(jié)束是否保持動(dòng)畫開始狀態(tài)
fillAfter 動(dòng)畫播放結(jié)束是否保持動(dòng)畫結(jié)束狀態(tài)

補(bǔ)間動(dòng)畫有4種,分別是:RotateAnimation-旋轉(zhuǎn)動(dòng)畫, TranslateAnimation-位移動(dòng)畫AlphaAnimation-透明度動(dòng)畫, ScaleAnimation-縮放動(dòng)畫,

由于這幾種動(dòng)畫創(chuàng)建的方式都一樣,唯獨(dú)就是部分屬性值不一樣,因此在這里就以 ScaleAnimation 為例,下面演示一下如何完成動(dòng)畫操作。

一共有兩種完成動(dòng)畫的方式,xml創(chuàng)建純代碼創(chuàng)建

1.在xml中創(chuàng)建完成動(dòng)畫

找到 res 文件夾,在下面新建一個(gè) Android Resource Directory,Resource type 選擇 anim。然后我們?cè)诶锩鎸懭胍韵麓a,根節(jié)點(diǎn)是什么,就是什么動(dòng)畫,當(dāng)然你也可以選擇 set 一次定義多個(gè)動(dòng)畫。

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="1"  設(shè)置縮放起始時(shí)的x軸的倍數(shù)
    android:fromYScale="1"  設(shè)置縮放起始時(shí)的y軸的倍數(shù)
    android:toXScale="50"   設(shè)置縮放結(jié)束時(shí)的x軸的倍數(shù)
    android:toYScale="50"   設(shè)置縮放起始時(shí)的y軸的倍數(shù)
    android:pivotX="50%"    設(shè)置縮放時(shí)以x軸的某點(diǎn)為中心進(jìn)行縮放
    android:pivotY="50%"    設(shè)置縮放時(shí)以y軸的某點(diǎn)為中心進(jìn)行縮放
                            這兩個(gè)屬性加起來就是以物體中心點(diǎn)向四周縮放
    android:duration="700"  動(dòng)畫完成時(shí)間
    android:fillAfter="false"/>  動(dòng)畫是否保持結(jié)束時(shí)最后一刻的狀態(tài)

然后就是在代碼中使用這段動(dòng)畫了,

//獲取控件
private val bgView = findViewById<View>(R.id.view)
//加載動(dòng)畫資源
scaleAnimation = AnimationUtils.loadAnimation(this,R.anim.btn_scale_anim)
//啟動(dòng)動(dòng)畫,和其他動(dòng)畫不同,補(bǔ)間動(dòng)畫啟動(dòng)是通過 view.startAnimation
bgView.startAnimation(scaleAnimation)

效果如下:

2.完全通過代碼創(chuàng)建實(shí)現(xiàn)動(dòng)畫
val imageView = findvViewById<ImageView>(R.id.iamgeView)

animation = ScaleAnimation(
            0f,//起始縮放倍數(shù)x軸
            1f,//結(jié)束縮放倍數(shù)x軸
            0f,//起始縮放倍數(shù)y軸
            1f,//結(jié)束縮放倍數(shù)x軸
            Animation.RELATIVE_TO_SELF,
            0.5f,//相對(duì)自身x軸0.5倍距離
            Animation.RELATIVE_TO_SELF,
            0.5f//相對(duì)自身y軸0.5倍距離
        ).apply {
            interpolator = LinearInterpolator()
            repeatMode = Animation.REVERSE
            duration = 5000
            repeatCount = Animation.INFINITE
        }
imageView.startAnimation(animation)

當(dāng)我開始執(zhí)行動(dòng)畫時(shí)就是以下效果:

四.屬性動(dòng)畫

屬性動(dòng)畫前面也提到了,通常是要在動(dòng)畫結(jié)束后有點(diǎn)擊事件時(shí)運(yùn)用。它使用起來很方便。屬性動(dòng)畫的一些屬性名稱以及對(duì)應(yīng)的值和漸變動(dòng)畫很多都一樣,只是屬性動(dòng)畫的暫停是 animator.pause() 。

屬性動(dòng)畫常用的有兩種 ObjectAnimatorValueAnimatorObjectAnimator 是直觀的給 Object 加上動(dòng)畫效果,能直觀地為我們展示動(dòng)畫,如 translationX 就是在x軸上移動(dòng),而 ValueAnimator 是能產(chǎn)生很多關(guān)于動(dòng)畫的值,我們將這些值賦給每個(gè)動(dòng)畫因子,就可以完成很多花里胡哨的動(dòng)畫,如,我手動(dòng)繪制一個(gè)這樣的加載動(dòng)畫(屏幕上方那一個(gè)),它的一個(gè)動(dòng)畫因子就是 startAngle(畫圓弧的起始角度) 。

下面就舉例講一個(gè)屬性動(dòng)畫 translationX。顧名思義,是在物體 x軸 方向上移動(dòng),向右移動(dòng)是正,向左移動(dòng)是負(fù)。

val v = findViewById<View>(R.id.view)
ObjectAnimator.ofFloat(v,"translationX",0f, height - 50f.apply {
    duration = 350
    interpolator = BounceInterpolator()
}.start()

由于是 ofFloat 所以參數(shù)都必須是 Float 類型!

  • 當(dāng)有多個(gè)動(dòng)畫時(shí)可以使用 AnimatorSet 設(shè)置同時(shí)播放或順序播放。
//同時(shí)播放
AnimatorSet().playTogether(動(dòng)畫一,動(dòng)畫二)
//順序播放,寫在前面的先播放
AnimatorSet().playSequentially(動(dòng)畫一,動(dòng)畫二)
  • 屬性動(dòng)畫允許添加事件監(jiān)聽
val v = findViewById<View>(R.id.view)
ObjectAnimator.ofFloat(v, "translationX", - 2f, 0f).apply {
            duration = 500
            interpolator = LinearInterpolator()
            addListener(
                onStart = {
                    //動(dòng)畫開始時(shí) TODO
                },
                onCancel = {
                    //動(dòng)畫取消時(shí) TODO
                },
                onEnd = {
                    //動(dòng)畫結(jié)束時(shí) TODO
                },
                onRepeat = {
                    //動(dòng)畫重復(fù)時(shí) TODO
                })
        }.start()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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