天天看點

Android屬性動畫 ObjectAnimatorObjectAnimator實戰-心跳動畫參考資料

轉載請标明出處:http://blog.csdn.net/zhaoyanjun6/article/details/118709616

本文出自【趙彥軍的部落格】

文章目錄

  • ObjectAnimator
  • 實戰-心跳動畫
  • 參考資料

ObjectAnimator

public final class ObjectAnimator extends ValueAnimator {
...
}
           

ObjectAnimator

繼承

ValueAnimator

, 是以

ObjectAnimator

擁有

ValueAnimator

一切特性。

相比于

ValueAnimator

ObjectAnimator

可能才是我們最常接觸到的類,因為

ValueAnimator

隻不過是對值進行了一個平滑的動畫過渡,但我們實際使用到這種功能的場景好像并不多。而

ObjectAnimator

則就不同了,它是可以直接對任意對象的任意屬性進行動畫操作的,比如說

View

alpha

屬性。

不過雖說

ObjectAnimator

會更加常用一些,但是它其實是繼承自

ValueAnimator

的,底層的動畫實作機制也是基于ValueAnimator來完成的,是以

ValueAnimator

仍然是整個屬性動畫當中最核心的一個類。那麼既然是繼承關系,說明

ValueAnimator

中可以使用的方法在

ObjectAnimator

中也是可以正常使用的,它們的用法也非常類似,這裡如果我們想要将一個

TextView

在5秒中内從正常變換成全透明,再從全透明變換成正常,就可以這樣寫:

ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
animator.setDuration(5000);
animator.start();
           

可以看到,我們還是調用了

ofFloat()

方法來去建立一個

ObjectAnimator

的執行個體,隻不過

ofFloat()

方法當中接收的參數有點變化了。這裡第一個參數要求傳入一個

object

對象,我們想要對哪個對象進行動畫操作就傳入什麼,這裡我傳入了一個

textview

。第二個參數是想要對該對象的哪個屬性進行動畫操作,由于我們想要改變

TextView

的不透明度,是以這裡傳入

"alpha"

。後面的參數就是不固定長度了,想要完成什麼樣的動畫就傳入什麼值,這裡傳入的值就表示将

TextView

從正常變換成全透明,再從全透明變換成正常。之後調用

setDuration()

方法來設定動畫的時長,然後調用

start()

方法啟動動畫,效果如下圖所示:

Android屬性動畫 ObjectAnimatorObjectAnimator實戰-心跳動畫參考資料

學會了這一個用法之後,其它的用法我們就可以舉一反三了,那比如說我們想要将

TextView

進行一次

360度

的旋轉,就可以這樣寫:

ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
animator.setDuration(5000);
animator.start();
           

可以看到,這裡我們将第二個參數改成了

"rotation"

,然後将動畫的初始值和結束值分别設定成

0和360

,現在運作一下代碼,效果如下圖所示:

Android屬性動畫 ObjectAnimatorObjectAnimator實戰-心跳動畫參考資料

那麼如果想要将TextView先向左移出螢幕,然後再移動回來,就可以這樣寫:

float curTranslationX = textview.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "translationX", curTranslationX, -500f, curTranslationX);
animator.setDuration(5000);
animator.start();
           

這裡我們先是調用了

TextView

getTranslationX()

方法來擷取到目前

TextView的translationX

的位置,然後

ofFloat()

方法的第二個參數傳入

"translationX"

,緊接着後面三個參數用于告訴系統

TextView

應該怎麼移動,現在運作一下代碼,效果如下圖所示:

Android屬性動畫 ObjectAnimatorObjectAnimator實戰-心跳動畫參考資料

然後我們還可以

TextView

進行縮放操作,比如說将

TextView

在垂直方向上放大3倍再還原,就可以這樣寫:

ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "scaleY", 1f, 3f, 1f);
animator.setDuration(5000);
animator.start();
           

這裡将ofFloat()方法的第二個參數改成了"scaleY",表示在垂直方向上進行縮放,現在重新運作一下程式,效果如下圖所示:

Android屬性動畫 ObjectAnimatorObjectAnimator實戰-心跳動畫參考資料

到目前為止,

ObjectAnimator

的用法還算是相當簡單吧,但是我相信肯定會有不少朋友現在心裡都有同樣一個疑問,就是

ofFloat()

方法的第二個參數到底可以傳哪些值呢?

目前我們使用過了

alpha

rotation

translationX

scaleY

這幾個值,分别可以完成淡入淡出、旋轉、水準移動、垂直縮放這幾種動畫,那麼還有哪些值是可以使用的呢?

其實這個問題的答案非常玄乎,就是我們可以傳入任意的值到

ofFloat()

方法的第二個參數當中。任意的值?相信這很出乎大家的意料吧,但事實就是如此。因為

ObjectAnimator

在設計的時候就沒有針對于

View

來進行設計,而是針對于任意對象的,它所負責的工作就是不斷地向某個對象中的某個屬性進行指派,然後對象根據屬性值的改變再來決定如何展現出來。

那麼比如說我們調用下面這樣一段代碼:

其實這段代碼的意思就是

ObjectAnimator

會幫我們不斷地改變

textview

對象中

alpha

屬性的值,從1f變化到0f。然後

textview

對象需要根據

alpha

屬性值的改變來不斷重新整理界面的顯示,進而讓使用者可以看出淡入淡出的動畫效果。

那麼

textview

對象中是不是有

alpha

屬性這個值呢?

沒有,不僅

textview

沒有這個屬性,連它所有的父類也是沒有這個屬性的!

這就奇怪了,

textview

當中并沒有alpha這個屬性,

ObjectAnimator

是如何進行操作的呢?其實

ObjectAnimator

内部的工作機制并不是直接對我們傳入的屬性名進行操作的,而是會去尋找這個屬性名對應的

get和set

方法,是以alpha屬性所對應的

get和set

方法應該就是:

public void setAlpha(float value);
public float getAlpha();
           

那麼

textview

對象中是否有這兩個方法呢?确實有,并且這兩個方法是由

View

對象提供的,也就是說不僅

TextView

可以使用這個屬性來進行淡入淡出動畫操作,任何繼承自

View

的對象都可以的。

既然

alpha

是這個樣子,相信大家一定已經明白了,前面我們所用的所有屬性都是這個工作原理,那麼View當中一定也存在着

setRotation()

getRotation()

setTranslationX()

getTranslationX()

setScaleY()

getScaleY()

這些方法,不信的話你可以到View當中去找一下。

實戰-心跳動畫

先上效果圖:

Android屬性動畫 ObjectAnimatorObjectAnimator實戰-心跳動畫參考資料

自定義 View

/**
 * @author : zhaoyanjun
 * @time : 2021/7/13
 * @desc :
 */
class MyView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {

    private var radius = 10f  //圓的半徑
        set(value) {
            field = value
            invalidate()
        }

    private val paint = Paint()

    init {
        paint.color = Color.BLUE
        paint.textSize = 8f
        paint.isAntiAlias = true
        paint.style = Paint.Style.FILL
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        //繪制圓
        canvas?.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), radius, paint)
    }
}
           

有一點很重要的是,

radius

的 set 方法中需要調用

invalidate()

方法,才能夠重新整理

view

我們再看執行動畫的部分

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var myView: MyView = findViewById(R.id.myView)
        
        //通過動畫,不斷的改變 radius 的值
        var objectAnimator =
            ObjectAnimator.ofFloat(myView, "radius", 200f, 500f, 200f)
        objectAnimator.duration = 600
        objectAnimator.interpolator = LinearInterpolator()
        objectAnimator.repeatCount = 20  //執行20次
        objectAnimator.start()
    }
}

           

參考資料

  • Android屬性動畫完全解析(上),初識屬性動畫的基本用法