Android屬性動(dòng)畫實(shí)踐

概述

在Android開發(fā)中,我們常用動(dòng)畫的實(shí)現(xiàn)方式有幾種:

  1. 幀動(dòng)畫(Gif的實(shí)現(xiàn)就是把動(dòng)畫拆分成一張張單獨(dú)的圖片唯笙,逐幀播放)
  2. 補(bǔ)間動(dòng)畫(用xml實(shí)現(xiàn)的一系列的動(dòng)畫,包括淡入淡出萄窜、縮放诈泼、平移、旋轉(zhuǎn))
  3. 屬性動(dòng)畫(Android 3.0版本引入的全新動(dòng)畫實(shí)現(xiàn)捅儒,后面詳細(xì)說(shuō)明)

屬性動(dòng)畫關(guān)鍵概念

插值器(TimeInterpolator)

學(xué)術(shù)點(diǎn)的說(shuō)法就是根據(jù)時(shí)間流逝的百分比計(jì)算出當(dāng)前屬性值改變的百分比液样。是不是有點(diǎn)蒙振亮,我們通俗點(diǎn)說(shuō)吧,其實(shí)就是根據(jù)時(shí)間的流逝鞭莽,計(jì)算出一個(gè)系數(shù)坊秸,后面我們會(huì)根據(jù)這個(gè)系數(shù)去改變目標(biāo)屬性的值,實(shí)現(xiàn)我們的目的澎怒。再簡(jiǎn)單的說(shuō)就是控制動(dòng)畫快慢的東西褒搔,不知道這么說(shuō)會(huì)不會(huì)被拍磚,不管了喷面,也算是自己的理解吧星瘾。

系統(tǒng)中已經(jīng)實(shí)現(xiàn)了很多插值器,我們基本上是不需要自己去定義的惧辈,常用的有:
LinearInterpolator(勻速)
AccelerateInterpolator (加速)
DecelerateInterpolator(減速)
看到這里琳状,就是控制動(dòng)畫的快慢嘛,哈咬像!

估值器 (TypeEvaluator)

學(xué)術(shù)點(diǎn)的說(shuō)法就是根據(jù)剛才時(shí)間插值器得出百分比計(jì)算得到目的的屬性值算撮。其實(shí)就是根據(jù)剛才TimeInterpolator得到的系數(shù)去改變當(dāng)前的屬性值,從而更新View县昂。

系統(tǒng)也已經(jīng)實(shí)現(xiàn)了很多的估值器肮柜,很多時(shí)候也是不需要自己去定義的,只有當(dāng)應(yīng)用到自定義對(duì)象的時(shí)候倒彰,會(huì)去自定義估值器审洞。
IntEvaluator:針對(duì)整型屬性
FloatEvaluator:針對(duì)浮點(diǎn)型屬性
ArgbEvaluator:針對(duì)Color屬性

使用估值器我們一般直接就使用ValueAnimator的ofFloat(float... values),ofInt(int... values)待讳,ofArgb(int... values)芒澜,不需要像插值器一樣需要通過setInterpolator去設(shè)置。

實(shí)例

先看下效果:

animation.gif

話不多說(shuō)创淡,直接上代碼痴晦,代碼中有相應(yīng)的注釋,這里就不多說(shuō)明了琳彩。

package com.example.anker.demo;

import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;

/**
 * Created by dylan.huang on 17/4/21.
 */

public class MyView extends View {

    Paint mPaint;
    int lineWidth = 10;
    int ratio = 50;
    int mColor = Color.BLUE;
    float rotate;

    public MyView(Context context) {
        super(context);
        init();
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(lineWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 由于動(dòng)畫中有更改顏色誊酌,所以這里每次onDraw都要重新設(shè)置下畫筆顏色
        mPaint.setColor(mColor);
        // 旋轉(zhuǎn)動(dòng)畫,直接旋轉(zhuǎn)畫布即可
        canvas.rotate(rotate, getWidth()/2, getHeight()/2);
        // 畫正方形露乏,ratio為可邊長(zhǎng)的一半
        canvas.drawRect(getWidth()/2-ratio/2, getHeight()/2-ratio/2, getWidth()/2+ratio/2, getHeight()/2+ratio/2, mPaint);
        // 畫圓形碧浊,ratio為半徑
        canvas.drawCircle(getWidth()/2  , getHeight()/2-2*ratio, ratio, mPaint);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void start() {
        // 旋轉(zhuǎn)動(dòng)畫,通過改變r(jià)otate值實(shí)現(xiàn)
        ValueAnimator rotateAni = ValueAnimator.ofFloat(0, 360);
        // 無(wú)限重復(fù)
        rotateAni.setRepeatCount(Animation.INFINITE);
        // 設(shè)置監(jiān)聽瘟仿,賦值給rotate
        rotateAni.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                rotate = (float) animation.getAnimatedValue();
                invalidate();
            }
        });

        // 放大動(dòng)畫箱锐,通過改變r(jià)atio實(shí)現(xiàn)
        ValueAnimator ratioAnimator = ValueAnimator.ofInt(50, 100);
        ratioAnimator.setInterpolator(new LinearInterpolator());
        ratioAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                ratio = (int) animation.getAnimatedValue();
            }
        });
        ratioAnimator.setRepeatCount(Animation.INFINITE);
        // 設(shè)置重復(fù)的模式為原樣恢復(fù),即放大后再按原路縮小劳较,這樣才不會(huì)出現(xiàn)跳動(dòng)
        ratioAnimator.setRepeatMode(ValueAnimator.REVERSE);

        // 顏色變化動(dòng)畫
        ValueAnimator colorAni = ValueAnimator.ofArgb(Color.BLUE, Color.GREEN);
        colorAni.setInterpolator(new LinearInterpolator());
        colorAni.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mColor = (int)animation.getAnimatedValue();
            }
        });
        colorAni.setRepeatCount(Animation.INFINITE);
        colorAni.setRepeatMode(ValueAnimator.REVERSE);

        // 多個(gè)動(dòng)畫同時(shí)運(yùn)行驹止,通過AnimatorSet進(jìn)行組合管理
        AnimatorSet set = new AnimatorSet();
        set.setDuration(1000);
        set.play(ratioAnimator).with(colorAni).with(rotateAni);
        set.start();
    }
}

我在例子中用的都是ValueAnimator浩聋,其實(shí)還有其它相關(guān)類,比如ObjectAnimator改變透明度:

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

是不是很方便幢哨,可以直接改變控件的屬性赡勘,簡(jiǎn)單明了嫂便。

另外還有ViewPropertyAnimator捞镰,用起來(lái)更方便,不過只有有限的方法毙替,比如讓view在x軸y軸都平衡500:


textview.animate().x(500).y(500).setDuration(5000)  
        .setInterpolator(new BounceInterpolator());  

最后最后岸售,再說(shuō)一個(gè)PropertyValuesHolder,它保存了動(dòng)畫過程中所需要操作的屬性和對(duì)應(yīng)的值厂画,通常和Keyframe一起使用凸丸。像實(shí)現(xiàn)一個(gè)View抖動(dòng)動(dòng)畫時(shí),你用上面的需要寫很多重復(fù)的動(dòng)畫進(jìn)行串聯(lián)起來(lái)袱院,但用Keyframe就可以很好的一次性把動(dòng)畫描述清楚屎慢。Keyframe其實(shí)就是動(dòng)畫的關(guān)鍵幀。舉個(gè)抖動(dòng)的實(shí)現(xiàn)例子:

Keyframe frame0 = Keyframe.ofFloat(0f, 0);
Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
Keyframe frame2 = Keyframe.ofFloat(1, 0);
PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2);
 Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder);
animator.setDuration(1000);
animator.start();

其實(shí)最后還是用到ObjectAnimator.ofPropertyValuesHolder忽洛,是通過屬性動(dòng)畫來(lái)執(zhí)行的腻惠。

總結(jié)

其實(shí)屬性動(dòng)畫給了我們更大的自由度,接口也很友好欲虚,可以讓我們按自己的想法去實(shí)現(xiàn)更酷炫的動(dòng)畫集灌。快投入屬性動(dòng)畫的懷抱吧复哆,它真的可以帶你飛哦P佬!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末梯找,一起剝皮案震驚了整個(gè)濱河市唆阿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌锈锤,老刑警劉巖驯鳖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異牙咏,居然都是意外死亡臼隔,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門妄壶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)摔握,“玉大人,你說(shuō)我怎么就攤上這事丁寄“碧剩” “怎么了泊愧?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)盛正。 經(jīng)常有香客問我删咱,道長(zhǎng),這世上最難降的妖魔是什么豪筝? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任痰滋,我火速辦了婚禮,結(jié)果婚禮上续崖,老公的妹妹穿的比我還像新娘敲街。我一直安慰自己,他們只是感情好严望,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布多艇。 她就那樣靜靜地躺著,像睡著了一般像吻。 火紅的嫁衣襯著肌膚如雪峻黍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天拨匆,我揣著相機(jī)與錄音姆涩,去河邊找鬼。 笑死涮雷,一個(gè)胖子當(dāng)著我的面吹牛阵面,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洪鸭,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼样刷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了览爵?” 一聲冷哼從身側(cè)響起置鼻,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蜓竹,沒想到半個(gè)月后箕母,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俱济,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年嘶是,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛛碌。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡聂喇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情希太,我是刑警寧澤克饶,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站誊辉,受9級(jí)特大地震影響矾湃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜堕澄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一邀跃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧奈偏,春花似錦坞嘀、人聲如沸躯护。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)棺滞。三九已至裁蚁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間继准,已是汗流浹背枉证。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留移必,地道東北人室谚。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像崔泵,于是被迫代替她去往敵國(guó)和親秒赤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

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

  • 【Android 動(dòng)畫】 動(dòng)畫分類補(bǔ)間動(dòng)畫(Tween動(dòng)畫)幀動(dòng)畫(Frame 動(dòng)畫)屬性動(dòng)畫(Property ...
    Rtia閱讀 6,153評(píng)論 1 38
  • 一: 傳統(tǒng) View 動(dòng)畫(Tween/Frame) 1.1 Tween 動(dòng)畫 主要有 4 中:縮放癌蚁、平移太颤、漸變垢袱、...
    dfg_fly閱讀 719評(píng)論 1 2
  • 對(duì)于android手機(jī)上的動(dòng)畫實(shí)現(xiàn)主要有三種,一種是幀動(dòng)畫潮售,一種是View動(dòng)畫,以及3.0以上提供的屬性動(dòng)畫锅风,所有...
    查理吃西瓜閱讀 6,524評(píng)論 1 39
  • Animation Animation類是所有動(dòng)畫(scale酥诽、alpha、translate皱埠、rotate)的基...
    四月一號(hào)閱讀 1,916評(píng)論 0 10
  • 本筆記的原文本鏈接 Property Animation Overview 屬性動(dòng)畫總覽 The property...
    Jaesoon閱讀 1,101評(píng)論 2 3