Android-屬性動畫

Android-屬性動畫

學習自

《Android開發藝術探索》
《屬性動畫相關的官方文檔》android

屬性動畫漫談

Android的屬性動畫是Android3.0 推出的,屬性動畫徹底改善了View動畫的弊端,若是不是一些地方還會用到View動畫屬性動畫早就將View動畫徹底替代了。屬性動畫之因此被稱之爲屬性動畫,是由於屬性動畫經過動態地改變View的屬性來實現動畫效果。好比說,屬性動畫經過改變一個View的X軸座標來實現移動View位置的動畫,經過屬性動畫移動了View的位置是真正意義上的改變了View的位置,而不是僅僅是像View動畫那樣將View的圖像顯示在指定位置。app

屬性動畫框架主要結構

image.png | left | 374x397

  • Animator,全部屬性動畫的父類,爲開始、結束屬性動畫和添加動畫監聽器提供了支持。
  • AnimatorSet,屬性動畫的合集
  • ValueAnimator, 僅僅是對數值的屬性動畫,並不能表如今UI上
  • ObjectAnimator,對View的屬性動畫

ValueAnimator

//設置ValueAnimator,1-100的浮點數之間的動畫漸變
val valueAnimator = ValueAnimator.ofFloat(1.0F, 100.0F).setDuration(1000)
//設置一個監聽器
valueAnimator.addUpdateListener {
    val value = it.animatedValue as Float
    Log.e("TAG", "Value=$value")
}
valueAnimator.start()

//輸出結果
07-23 15:46:00.944 13240-13240/top.littledavid.studyanimation E/TAG: Value=1.0
07-23 15:46:00.945 13240-13240/top.littledavid.studyanimation E/TAG: Value=1.0
07-23 15:46:00.978 13240-13240/top.littledavid.studyanimation E/TAG: Value=1.0705773
07-23 15:46:01.010 13240-13240/top.littledavid.studyanimation E/TAG: Value=1.609426
//............................................
07-23 15:46:01.431 13240-13240/top.littledavid.studyanimation E/TAG: Value=47.857613
07-23 15:46:01.450 13240-13240/top.littledavid.studyanimation E/TAG: Value=50.5
07-23 15:46:01.465 13240-13240/top.littledavid.studyanimation E/TAG: Value=53.142387
07-23 15:46:01.484 13240-13240/top.littledavid.studyanimation E/TAG: Value=55.6226
07-23 15:46:01.499 13240-13240/top.littledavid.studyanimation E/TAG: Value=58.243496
//...........................................
07-23 15:46:01.915 13240-13240/top.littledavid.studyanimation E/TAG: Value=99.73422
07-23 15:46:01.931 13240-13240/top.littledavid.studyanimation E/TAG: Value=99.92943
07-23 15:46:01.948 13240-13240/top.littledavid.studyanimation E/TAG: Value=100.0

上面的代碼是一個ValueAnimator的Demo,ValueAnimator是僅僅是一種對數值的動畫,ofFloat() 方法支持任意參數,若是指定了那麼就會在規定時間內,完成數值的漸變。輸出結果上咱們能夠看出來,ValueAnimator平滑的從1過渡到了100。這裏的數值的變化是平滑線性的,若是你不想要這種效果,那麼可使用 差值器 來加速或者減速。關於差值器咱們會在另外一章提到。框架

由於ValueAnimator不能做用於對象,僅僅是對數值作了一個動畫,若是咱們想將ValueAnimator做爲動畫的話,須要在ValueAnimator的動畫監聽中來手動地更新對象。ide

/**
創建一個簡單的Person類,接線來咱們將會經過ValueAnimator來更新此對象的Age
*/
class Person(var name: String, var age: Int) {
    override fun toString(): String {
        return "I am is $name; I am $age years old!"
    }
}

var person = Person("魯迅認識的那隻猹", 0)
ValueAnimator.ofInt(1, 50).apply {
    duration = 3000
    //動畫的每一幀都會調用此監聽的回調
    //咱們能夠在此監聽中更新咱們的對象
    addUpdateListener {
        person.age = it.animatedValue as Int
        Log.e("TAG", person.toString())
    }
    start()
}
/**
07-23 16:11:28.331 14623-14623/top.littledavid.studyanimation E/TAG:
-------------------------------------
07-23 16:11:28.882 14623-14623/top.littledavid.studyanimation E/TAG:
-------------------------------------
07-23 16:11:31.332 14623-14623/top.littledavid.studyanimation E/TAG:
*/

ObjectAnimator

下面是一個經過ObjectAnimator來更改View的透明度的動畫學習

alpha_object_animator.gif | left | 369x162

/**
參數解釋
1. 動畫做用的對象
2. 要更改的屬性
3. 設置動畫漸變的數值
*/
ObjectAnimator.ofInt(dogIV, "alpha", 0, 255).setDuration(3000).start()

ObjectAnimator的經常使用屬性和方法:動畫

  • propertyName 屬性動畫做用對象的屬性的名稱
  • duration 屬性動畫持續的時間
  • valueFrom 屬性的
  • values 屬性動畫的值
  • startDelay 動畫延遲,當調用start方法後,多少毫秒後開始動畫
  • repeatCount 屬性動畫重複的次數 ObjectAnimator.INFINITE(-1) 表示無線循環
  • repeatMode 屬性動畫重複的方式爲 ObjectAnimator.RESTARTObjectAnimator.REVERSE Restart表示從新開始,Reverse表示動畫翻轉交替進行。
  • ObjectAnimator.of Type指的是數據類型,好比說Int Float等

屬性動畫也能夠經過XMl文件來定義,須要放在 res/animator 目錄下:this

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="alpha"
    android:repeatCount="0"
    android:repeatMode="restart"
    android:valueFrom="0"
    android:valueTo="255"
    android:valueType="intType" />

代碼調用rest

var animator = AnimatorInflater.loadAnimator(this, R.animator.alpa_animator)
animator.setTarget(dogIV)
animator.start()

對任意屬性作動畫

經過上面的Demo的學習,可以得知屬性動畫的原理以下:code

屬性動畫要求其做用的對象的必須爲該屬性提供get和set方法,屬性動畫經過外界傳遞的該屬性的初始值和最終值,以動畫的形式來不斷地調用 set 方法賦值,隨着時間的推移,隨着時間的推移該值會愈來愈接近最終值,若是想要動畫生效須要知足一下的條件:xml

  1. 對象必須提供了set<屬性> 方法,若是動畫沒有提供初始值,那麼屬性動畫還會去調用get方法來獲取屬性的值,做爲初始值,若是不知足條件則Crash。
  2. set方法對屬性做用的改變必須可以以某種形式反映出來,好比說UI改變,不然,動畫不生效可是不會Crash。

那麼如今有一個問題

經過屬性動畫在3秒內將Button的長度從50px改到500px.

咱們都知道Button的是沒有提供setWidth方法的。因此咱們不能直接設置width,因此咱們須要對Button作一層包裝,經過一個包裝類來包裝一下Button對象而且提供get/setWidth 方法。

fun startAlphaObjectAnimator(view: View) {
    ObjectAnimator.ofInt(ButtonWrapper(testBtn), "width", 50, 500)
        .setDuration(3000)
        .start()
}

//Kotlin的寫法要比Java的簡化,直接經過定義屬性來解決
private class ButtonWrapper(var targetBtn: Button) {
    var width = targetBtn.width
        set(value) {
            targetBtn.layoutParams.width = value
        }
}

在上面的代碼中咱們爲Button類作了一些封裝提供了get和set方法,由於Button不可以直接設置寬度,這是一種很好的解決思路。對一個對象的不能直接設置屬性動畫的屬性來設置屬性動畫有一下集中解決辦法:

  1. 若是可以修改類,那麼提供上 get 和 set
  2. 經過包裝原有的類的對象,在包裝類中提供get和set方法
  3. 經過ValueAnimator來實現動畫,在監聽中更新屬性

除非特殊聲明不然,本博客文章均屬 魯迅認識的那隻猹 原創,未經許可禁止轉載,不然將保留追究法律責任的權利。

若是本博客損害了您的相關權益,請及時聯繫我,我將妥善處理。

相關文章
相關標籤/搜索