天天看點

Android屬性動畫與自定義屬性動畫一.動畫基礎知識二.動畫實際示例三.結語

  • 一.動畫基礎知識
    • 1.動畫分類
    • 2.什麼時候用什麼動畫?
  • 二.動畫實際示例
    • 1.ObjectAnimator實作普通屬性動畫
    • 2.ObjectAnimator實作自定義動畫
    • 3.使用ValueAnimator實作動畫
    • 4.RecyclerView單個Item的屬性動畫
  • 三.結語

一.動畫基礎知識

1.動畫分類

補間動畫:Tween Animation

幀動畫:Frame Animation

屬性動畫:Property Animation

2.什麼時候用什麼動畫?

1.補間動畫和幀動畫都是作用于View,是以兩者又被稱為View Animation,可以在View對象上執行一系列的簡單變換,比如位置、尺寸、旋轉、透明度等。注意:執行這兩種動畫時View的焦點是沒有變的,如果你的View涉及到點選事件等等用該類動畫就不合适。

2.屬性動畫功功能就比較強大了,而且執行動畫時View的焦點也是實時變化的。比如監聽手機的方向傳感器來執行設定界面的旋轉,這時候使用屬性動畫比較合适。還可以通過ValueAnimator控制執行的開始點和結束點,比如一個View關閉的效果。

二.動畫實際示例

1.ObjectAnimator實作普通屬性動畫

public static ObjectAnimator ofFloat(Object target, String propertyName, float… values) {}

一般是調用靜态函數ofFloat初始化一個ObjectAnimator,幾個參數的含義

target:要執行動畫的View

propertyName:要執行View的屬性,該View必須有set和get方法才可設定

values:這是一個可變參數,可以傳入幾個值,開始值,中間值,結束值,注意:傳入0表示View在初始位置

執行個體1:多個View同時執行一個旋轉動畫

//多個View同時執行一個旋轉動畫
private fun startRotationAnim(degree: Float) {
        val animatorSet = AnimatorSet()
        val animatorShotAbumImg = ObjectAnimator.ofFloat(shotAlbumImg, "rotation", degree)
        val animatorShotAlbumCardView = ObjectAnimator.ofFloat(cardView, "rotation", degree)
        val animatorShotMoreImg = ObjectAnimator.ofFloat(shotMoreImg, "rotation", degree)
        val animatorShotSwitchCamera = ObjectAnimator.ofFloat(shotSwitchCamera, "rotation", degree)
        val animatorCountDownTv = ObjectAnimator.ofFloat(countDownTv, "rotation", degree)
        val animatorShotBeautyImg = ObjectAnimator.ofFloat(shotBeautyImg, "rotation", degree)
        animatorSet.play(animatorShotAbumImg)
                .with(animatorShotMoreImg)
                .with(animatorShotSwitchCamera)
                .with(animatorCountDownTv)
                .with(animatorShotAlbumCardView)
                .with(animatorShotBeautyImg)
        animatorSet.duration = 
        animatorSet.start()
    }
           

執行個體2:一個View如何同時執行旋轉+平移動畫

使用PropertyValuesHolder類

private fun startAnim(degree: Float) {
        var videoScaleX: PropertyValuesHolder ?= null
        var videoScaleY: PropertyValuesHolder ?=null
        var videoRotation: PropertyValuesHolder ?= null
        var scale :Float = f
        val layoutParams = mRootView!!.surfaceView.layoutParams as FrameLayout.LayoutParams
        scale = layoutParams.width / layoutParams.height.toFloat()
        videoScaleX = PropertyValuesHolder.ofFloat("scaleX", scale)
        videoScaleY = PropertyValuesHolder.ofFloat("scaleY", scale)
        videoRotation = PropertyValuesHolder.ofFloat("rotation", degree)
        val videoAnimation = ObjectAnimator.ofPropertyValuesHolder(mRootView!!.surfaceView, videoScaleX, videoScaleY, videoRotation)
        val animatorSet = AnimatorSet()
        animatorSet.play(videoAnimation)
        animatorSet.duration = 
        animatorSet.start()
        }
           

2.ObjectAnimator實作自定義動畫

ObjectAnimator實作自定義動畫隻需要把propertyName定義成該View沒有的屬性,然後在onAnimationUpdate回調函數中處理相關的邏輯即可,動畫可以是一個3秒或5秒的動畫,也可以是一個常駐動畫。

執行個體1:3秒自定義動畫

mAnimator = ObjectAnimator
                .ofFloat(fl_container, "liuxu", f, f)
        mAnimator!!.duration = 
        mAnimator!!.start()
        CommonPreference.putBoolean(CommonPreference.IS_FIRST_FRAME, true)
        mIsFirstFrame = true
        mAnimator?.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener {
            override fun onAnimationUpdate(p0: ValueAnimator?) {
            //do something what you want
            //處理自己的動畫邏輯
             }
           

執行個體2:常駐動畫

在1的基礎上設定動畫為無限循環動畫

mCurrentSelectAnimator!!.repeatCount = ValueAnimator.INFINITE

注意:動畫的停止方式

//停止無限循環動畫的邏輯
                if (mCurrentSelectAnimator != null) {
                    mCurrentSelectAnimator!!.repeatMode = ValueAnimator.RESTART
                    mCurrentSelectAnimator!!.end()
                    //這句是關鍵點,隻将動畫結束動畫是不會停止的
                    fl_guild_current_select.clearAnimation()
                    mCurrentSelectAnimator = null
                }
           

3.使用ValueAnimator實作動畫

ValueAnimator本身并不能執行動畫,他隻是一個控制器,可以控制你設定的開始點到結束點按照時間一步一步過度執行.

//關閉動畫
    fun startCloseAnim() {
        //設定動畫的初始值和結束值
        val va = ValueAnimator.ofInt(, MoliveKit.getPixels( / f))
        val layoutParams = login_collect.fl_login_top.layoutParams
        val layoutParams1 = login_collect.fl_login_bottom.layoutParams
        va.addUpdateListener { animation ->
            //擷取中間值
            val h = animation?.animatedValue as Int
            //給View重新設定高度達到動畫的效果
            layoutParams.height = h + login_collect.fl_login_top.height
            login_collect.fl_login_top.layoutParams = layoutParams
            login_collect.fl_login_top.requestLayout()
            layoutParams1.height = h + login_collect.fl_login_bottom.height
            login_collect.fl_login_bottom.layoutParams = layoutParams1
            login_collect.fl_login_bottom.requestLayout()
        }
        va.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator?) {
                super.onAnimationEnd(animation)
                mLogInListener?.onCollectEnd()
            }

            override fun onAnimationStart(animation: Animator?) {
                super.onAnimationStart(animation)
            }
        })
        va.duration = 
        va.start()
    }
           

4.RecyclerView單個Item的屬性動畫

調用代碼

//這裡是通過xml檔案實作的,代碼的話一樣的道理
detailRecyclerView.layoutAnimation = AnimationUtils.loadLayoutAnimation(context, R.anim.anim_recyclerview_left)
detailRecyclerView.adapter.notifyDataSetChanged()
detailRecyclerView.scheduleLayoutAnimation()
           

anim_recyclerview_left檔案

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/item_beauty_detail_left"
    android:animationOrder="normal"
    android:interpolator="@android:anim/overshoot_interpolator"/>
           

item_beauty_detail_left檔案

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300">
    <translate
        android:interpolator="@android:anim/decelerate_interpolator"
        android:fromXDelta="-100%p"
        android:toXDelta="0" />

    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator" />

</set>
           

三.結語

不足之處請指正,希望大家共同學習,謝謝!

有什麼更炫酷的動畫,好的開源庫大家都可以分享出來共同研究!