自定義View之動畫篇-屬性動畫

文章首發(fā)于個人博客
任何形式的轉載都請聯(lián)系作者獲得授權并注明出處。

一铝宵、基本概念

屬性動畫就是在一定時間間隔內(nèi),通過不斷對值進行改變,并不斷將該值賦給對象的屬性鹏秋,從而實現(xiàn)該對象在該屬性上的動畫效果尊蚁。

二、動畫

1侣夷、View中的方法

我們可以對View調(diào)用以下屬性實現(xiàn)動畫

View中的方法 功能
setTranslationX()横朋、setTranslationY()setTranslationZ() 設置X百拓、Y琴锭、Z軸平移
setX()setX()衙传、setX() 設置X祠够、Y、Z軸絕對位置
setRotation()粪牲、setRotationX()古瓤、setRotationY() 設置平面、X腺阳、Y軸旋轉
setScaleX()落君、setScaleY() 設置X、Y方向縮放
setAlpha() 設置透明度

2亭引、ValueAnimator

屬性動畫機制中最核心的一個類绎速,ObjectAnimator和ViewPropertyAnimator都是通過這個這個實現(xiàn)的。ValueAnimator是通過不斷控制值的變化焙蚓,再不斷添加屬性纹冤,從而實現(xiàn)動畫效果

使用方法

  1. 初始化ValueAnimator,設置各種屬性
  2. 給ValueAnimator設置監(jiān)聽器购公,通過getAnimatedValue()拿到變化值后更新控件萌京。
常用方法 功能
ofInt() 返回一個int型變化的ValueAnimator
ofFloat() 返回一個float型變化的ValueAnimator
ofObject 返回一個object型變化的ValueAnimator。

1.1宏浩、設置顏色變化

我們這里并沒有使用ofArgb這個屬性知残,因為這個方法是在API21以上使用的,在低版本上不兼容比庄。

final View view = findViewById(R.id.view);
//以整型數(shù)值的形式求妹,過渡到結束值
ValueAnimator animator = ValueAnimator.ofInt(0xffff00ff, 0xffffff00, 0xffff00ff);
//設置求值器
animator.setEvaluator(new ArgbEvaluator());
//設置動畫的播放時長
animator.setDuration(1000);
//設置動畫重復播放次數(shù),ValueAnimator.INFINITE為無限重復
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        int currentValue = (Integer) animation.getAnimatedValue();
         Log.i(TAG, "onAnimationUpdate: "+currentValue);
         view.setBackgroundColor(currentValue);
         view.requestLayout();
    }
});
animator.start();

1.2、ofObject()的使用

ofInt和ofFloat是針對Int值和Float值的變化佳窑,但是制恍,我們只能控制一個值的變化,但是當我們需要實現(xiàn)多值變化時神凑,它們就不再滿足我們的需求净神。

//設置變化的值
ValueObject startObjectVal = new ValueObject(1f, 0);
ValueObject endObjectVal = new ValueObject(0f, 360);
ValueAnimator animator = ValueAnimator.ofObject(new Evaluator(), startObjectVal, endObjectVal);
animator.setDuration(3000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        view.setAlpha(((ValueObject) animation.getAnimatedValue()).alphaValue);
        //可以設置各種動畫
        view.setRotation(((ValueObject) animation.getAnimatedValue()).rotateValue);
        view.requestLayout();
    }
});
animator.start();

》》設置估值器,估值器的作用覺得值得變化順序《《

//下面具體講解
class Evaluator implements TypeEvaluator<ValueObject> {
    @Override
    public ValueObject evaluate(float fraction, ValueObject startValue, ValueObject endValue) {
        float alphaValue = startValue.alphaValue + (endValue.alphaValue - startValue.alphaValue) *          fraction;
        float rotateValue = startValue.rotateValue + (endValue.rotateValue - startValue.rotateValue) * fraction;
        return new ValueObject(alphaValue, rotateValue);
    }
}

//創(chuàng)建對象,保存透明度和旋轉的值得變化
class ValueObject {
    float alphaValue;//透明度
    float rotateValue;//旋轉

    ValueObject(float alphaValue, float rotateValue) {
        this.alphaValue = alphaValue;
        this.rotateValue = rotateValue;
    }
}

1.3强挫、屬性和方法整理

常用的屬性

方法 解釋 方法 解釋
setDuration 設置動畫總時長,單位毫秒薛躬。 getDuration 獲取動畫總時長
setFrameDelay 設置每一幀之間間隔多少毫秒 getFrameDelay 獲取每一幀之間間隔多少毫秒
setInterpolator 設置動畫的插值器 getInterpolator 獲取當前使用的插值器
setRepeatCount 設置重復次數(shù) getRepeatCount 獲取重復次數(shù)
setRepeatMode 設置重復模式俯渤。有RESTART(正序)和REVERSE(倒序) getRepeatMode 獲取重復模式
setStartDelay 設置開始前延遲毫秒數(shù) getStartDelay 獲取開始前延遲毫秒數(shù)
getAnimatedValue 獲取計算出來的當前屬性值 getAnimatedValue 獲取計算出來的當前某個屬性的值
setEvaluator 設置求值器 setFloatValues 設置Float型變化值,設置初始值型宝、中間值八匠、結束值
setIntValues 設置Int型變化值,設置初始值趴酣、中間值梨树、結束值 setObjectValues 設置Object型變化值,設置初始值岖寞、中間值抡四、結束值

常用的方法

方法 解釋 方法 解釋
addUpdateListener 添加值變化監(jiān)聽器 addUpdateListener 添加動畫狀態(tài)監(jiān)聽器
start 開始動畫 pause 暫停動畫
resume 繼續(xù)動畫 cancel 取消動畫
end 動畫結束 reverse 倒序播放動畫
isRunning 判斷是否在正在運行 isStarted 判斷是的開始播放

1.4、估值器和插值器(重點)

估值器--TypeEvaluator:決定值的具體變化順序

估值器的使用我們上面已經(jīng)學習過了仗谆,在這里對估值器的具體使用簡單的解釋指巡。

//實現(xiàn)了TypeEvaluator接口
public class FloatEvaluator implements TypeEvaluator {  
    
    /**
    * fraction:表示動畫完成度
    * startValue:動畫的初始值
    * endValue:動畫的結束值
    * /
    public Object evaluate(float fraction, Object startValue, Object endValue) {  
        //用初始值加上動畫完成度乘以結束值和初始值之間的差值
    }  
}

插值器--Interpolator:決定值的速度變化順序

使用方法:

setInterpolator(Interpolator interpolator)//設置速度插值器

常用的插值器:

  • LinearInterpolator:線性勻速變化
  • AccelerateDecelerateInterpolator:先加速再減速
  • AccelerateInterpolator:持續(xù)加速
  • DecelerateInterpolator:持續(xù)減速直到 0
  • AnticipateInterpolator:先回拉一下再進行正常動畫軌跡
  • OvershootInterpolator:動畫會超過目標值一些,然后再彈回來
  • AnticipateOvershootInterpolator:先回拉一下再進行正常動畫軌跡隶垮,最后動畫會超過目標值一些藻雪,然后再彈回來
  • BounceInterpolator:在目標值來回跳動

3、ObjectAnimator

直接對對象的屬性值進行改變操作狸吞,從而實現(xiàn)動畫效果勉耀,內(nèi)部是有ValueAnimator實現(xiàn),因此其也有ofXXX()方法蹋偏,這里接受的參數(shù)不一樣了便斥,具體的就不整理了,常用屬性和常用方法和ValueAnimator一致

使用方法:

  1. 對于自定義控件威始,使用setter / getter 方法椭住;
  2. 調(diào)用 ObjectAnimator.ofXXX() 創(chuàng)建 ObjectAnimator 對象,設置常用屬性字逗。
  3. 調(diào)用 start() 方法執(zhí)行動畫

方法:ofFloat(Object target, String propertyName, float... values)

參數(shù):

  • target:我們需要控制動畫的對象

  • propertyName:設置動畫效果(傳入任意屬性值)

    這里傳入的參數(shù)京郑,其實是調(diào)用了ValueAnimatorsetXXX()方法和getXXX()方法,具體的代碼就不貼了葫掉。

    • alpha:透明度
    • rotation些举,RotationXRotationY:旋轉
    • translationX 俭厚,translationY:平移
    • ScaleX户魏,scaleY :縮放
    • values:自定義屬性
  • values:值

》》自定義圓形進度條《《

完整代碼在線地址:Github在線地址

ProPress.java

我們在Activity中,給動畫設置了一個屬性progress,我們在ProPress.java中,用getProgress()setProgress方法叼丑,這樣系統(tǒng)會自動調(diào)用該對象屬性的set() & get()方法進行賦值关翎。

/**
 * Created by Active_Loser on 2018/10/22.
 * Content: 自定義圓形進度條
 */
public class ProPress extends View {

    //.....
    private int progress = 0;

    public float getProgress() {
        return progress;
    }

    public void setProgress(int progress) {
        this.progress = progress;
        invalidate();
    }
    
    //.....
    
    @Override
    protected void onDraw(Canvas canvas) {
        int width = getWidth();
        int height = getHeight();
        //繪制圓弧
        RectF arcRectF = new RectF(20, 20, width-20, height-20);
        //progress設置值為0-100,因此需要乘3.6
        canvas.drawArc(arcRectF, 135, progress * 3.6f, false, mArcPaint);
        canvas.drawText(progress + "%", width/2, height/2-(mArcPaint.ascent() + mArcPaint.descent()) / 2, mTextPaint);
    }
}

XML:

<com.example.active.loser.views.level3.ProPress
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:layout_centerInParent="true"
    android:id="@+id/view"/>

Activity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final ProPress view = findViewById(R.id.view);
    // 創(chuàng)建 ObjectAnimator 對象
    ObjectAnimator animator = ObjectAnimator.ofInt(view, "progress", 0, 100);
    //持續(xù)時長4秒
    animator.setDuration(4000);
    animator.setInterpolator(new FastOutSlowInInterpolator());
    animator.start();
}

4鸠信、ViewPropertyAnimator

ValueAnimator纵寝、ObjectAnimator、ViewPropertyAnimator三者使用難度和靈活性逐漸遞減星立,因此我們盡量選擇簡單的使用

使用方法

view.animate().動畫();  

常用的動畫如下表所示:

View中的方法 對于中的方法ViewPropertyAnimator 功能
setTranslationX() translationX()爽茴、translationXBy() 設置X軸平移
setTranslationY() translationY()绰垂、translationYBy() 設置Y軸平移
setTranslationZ() translationZ()室奏、translationZBy() 設置Z軸平移
setX()setX()劲装、setX() x()胧沫、xBy()y()占业、yBy()琳袄、z()zBy() 設置X纺酸、Y窖逗、Z軸絕對位置
setRotation() rotation()rotationBY() 設置平面軸旋轉
setRotationX() rotationX()餐蔬、rotationXBy() 設置X軸旋轉
setRotationY() rotationY()碎紊、rotationYBy() 設置Y軸旋轉
setScaleX() scaleX()scaleX()By 設置X方向縮放
setScaleY() scaleY()樊诺、scaleYBy() 設置Y方向縮放
setAlpha() alpha()仗考、alphaBy() 設置透明度

特點:

  • by:變化偏移、無by:變化到

    即:加上By的意思是词爬,繼續(xù)動畫這么多數(shù)值秃嗜,不加By的意思是動畫到這個數(shù)值。

簡單的使用:

view.animate()
.setDuration(5000)
.zBy(10)
.setInterpolator(new BounceInterpolator())
.setStartDelay(1000)
.withLayer()//是否開啟硬件加速
//監(jiān)聽
.setListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {
    }
    @Override
    public void onAnimationEnd(Animator animation) {
    }
    @Override
    public void onAnimationCancel(Animator animation) {
    }
    @Override
    public void onAnimationRepeat(Animator animation) {
    }
})
.setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
    }
})
.withEndAction(new Runnable() {
    @Override
    public void run() {
    }
})
.withStartAction(new Runnable() {
    @Override
    public void run() {
    }
})
.start();
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末顿膨,一起剝皮案震驚了整個濱河市锅锨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌恋沃,老刑警劉巖必搞,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異囊咏,居然都是意外死亡恕洲,警方通過查閱死者的電腦和手機塔橡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來霜第,“玉大人葛家,你說我怎么就攤上這事∶诶啵” “怎么了癞谒?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長末誓。 經(jīng)常有香客問我,道長书蚪,這世上最難降的妖魔是什么喇澡? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮殊校,結果婚禮上晴玖,老公的妹妹穿的比我還像新娘。我一直安慰自己为流,他們只是感情好呕屎,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著敬察,像睡著了一般秀睛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上莲祸,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天蹂安,我揣著相機與錄音,去河邊找鬼锐帜。 笑死田盈,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的缴阎。 我是一名探鬼主播允瞧,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蛮拔!你這毒婦竟也來了述暂?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤建炫,失蹤者是張志新(化名)和其女友劉穎贸典,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體踱卵,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡廊驼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年据过,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妒挎。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡绳锅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酝掩,到底是詐尸還是另有隱情鳞芙,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布期虾,位于F島的核電站原朝,受9級特大地震影響,放射性物質發(fā)生泄漏镶苞。R本人自食惡果不足惜喳坠,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望茂蚓。 院中可真熱鬧壕鹉,春花似錦、人聲如沸聋涨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牍白。三九已至脊凰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茂腥,已是汗流浹背笙各。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留础芍,地道東北人杈抢。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像仑性,于是被迫代替她去往敵國和親惶楼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容