Android屬性動(dòng)畫的使用(上)

前言:

安卓里面由于補(bǔ)間動(dòng)畫,只是變化的是視圖的內(nèi)容换衬,但是屬性的話痰驱,是沒有變的证芭,就是以前大家在使用動(dòng)畫的時(shí)候,如果在tagView(目標(biāo)視圖)上設(shè)置了監(jiān)聽事件担映,但是废士,當(dāng)tagView在移動(dòng)的時(shí)候,點(diǎn)擊事件還在原位置蝇完,這樣很不方便官硝,后面在API3.0以后就新增了屬性動(dòng)畫,很好的解決了以上問題短蜕,而且新增的功能還可以擴(kuò)展很多的動(dòng)畫效果氢架,下面就先來說說ValueAnimator的重要性

分析:

動(dòng)畫,簡單來說就是在一段時(shí)間里面進(jìn)行一系列視圖的變化朋魔,也就是必須有一定的過程岖研,在數(shù)學(xué)里面也是就時(shí)間段,而不是時(shí)間刻警检,(小裝個(gè)逼缎玫,嘻嘻!)
一解滓、ValueAnimator(非常重要的):
1.首先ValueAnimator繼承于父類的Animator,而它的實(shí)現(xiàn)子類ObjectAnimator以及TimeAnimator,暫時(shí)這里先不說這兩個(gè)子類
2.學(xué)習(xí)新的類筝家,肯定要先了解其API的使用:

ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 1);
        valueAnimator.setEvaluator();//設(shè)置評(píng)估者
        valueAnimator.setRepeatCount();//設(shè)置動(dòng)畫重復(fù)的次數(shù)
        valueAnimator.setInterpolator();//設(shè)置動(dòng)畫的插值器洼裤;也就是動(dòng)畫如何變化,就像速度的描述加速度一樣
        valueAnimator.setDuration();//動(dòng)畫的時(shí)間
        valueAnimator.setStartDelay();//動(dòng)畫在開始之前延遲多少
        valueAnimator.setRepeatMode();//動(dòng)畫重復(fù)的方式溪王;RESTART:開始-結(jié)束 開始-結(jié)束腮鞍;REVERSE:開始-結(jié)束-開始 
        valueAnimator.addListener();//動(dòng)畫的監(jiān)聽
        valueAnimator.addUpdateListener();//動(dòng)畫屬性值更新的監(jiān)聽

二、ValueAnimator的重要使用:
1.setEvaluator()的方法:

public class IntEvaluator implements TypeEvaluator<Integer> {

public Integer evaluate(float fraction, Integer startValue, Integer endValue) 
{
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt)); 
    }
}

里面有三個(gè)參數(shù):

  • fraction:這個(gè)值是由插值器返回的一個(gè)百分比的數(shù)值莹菱,范圍0~1之間
  • startValue:起始值
  • endValue:結(jié)束值

這個(gè)評(píng)估者的類里面就是返回一個(gè)一直在疊加的值移国,也就是一段時(shí)間里面變化的值,如果能得到這個(gè)值道伟,是不是很多的動(dòng)畫效果就迎刃而解了迹缀,因?yàn)閂iew變化的時(shí)候,其實(shí)就是時(shí)期位置在一段時(shí)間里面不斷的變化蜜徽,當(dāng)間隔小于肉眼所感知的崢祝懂,就認(rèn)為是在動(dòng)

2.addUpdateListener();這個(gè)方法就是監(jiān)聽動(dòng)畫在動(dòng)的過程中的回調(diào),那么這里面應(yīng)該有我們想要的東西

valueAnimator.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
             @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                 Object animatedValue = animation.getAnimatedValue();//這個(gè)不正式我們上面?zhèn)鞯?                 值嗎
                //在這里面我們是不是可以設(shè)置View的透明度拘鞋,平移砚蓬,旋轉(zhuǎn),以及放大盆色,其實(shí)一段時(shí)間里面這還可以變換顏色
            }
        });

3.當(dāng)然顏色變換的評(píng)估者系統(tǒng)已經(jīng)給大家定義好了:

public class ArgbEvaluator implements TypeEvaluator {
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        int startInt = (Integer) startValue;
        int startA = (startInt >> 24);
        int startR = (startInt >> 16) & 0xff;
        int startG = (startInt >> 8) & 0xff;
        int startB = startInt & 0xff;

        int endInt = (Integer) endValue;
        int endA = (endInt >> 24);
        int endR = (endInt >> 16) & 0xff;
        int endG = (endInt >> 8) & 0xff;
        int endB = endInt & 0xff;

        return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
                (int)((startR + (int)(fraction * (endR - startR))) << 16) |
                (int)((startG + (int)(fraction * (endG - startG))) << 8) |
                (int)((startB + (int)(fraction * (endB - startB))));
    }
}

大家要做變背景色的效果是不是很簡單就可以實(shí)現(xiàn)

三灰蛙、ValueAnimator的高級(jí)用法

對(duì)一個(gè)Point作用:

public class Point {  
  
    private float x;  
  
    private float y;  
  
    public Point(float x, float y) {  
        this.x = x;  
        this.y = y;  
    }  
  
    public float getX() {  
        return x;  
    }  
  
    public float getY() {  
        return y;  
    }  
  
}  

Point類非常簡單祟剔,只有x和y兩個(gè)變量用于記錄坐標(biāo)的位置,并提供了構(gòu)造方法來設(shè)置坐標(biāo)摩梧,以及get方法來獲取坐標(biāo)物延。接下來定義PointEvaluator,如下所示:

public class PointEvaluator implements TypeEvaluator{  
  
    @Override  
    public Object evaluate(float fraction, Object startValue, Object endValue) {  
        Point startPoint = (Point) startValue;  
        Point endPoint = (Point) endValue;  
        float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());  
        float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());  
        Point point = new Point(x, y);  
        return point;  
    }  
  
}  

可以看到障本,PointEvaluator同樣實(shí)現(xiàn)了TypeEvaluator接口并重寫了evaluate()方法教届。其實(shí)evaluate()方法中的邏輯還是非常簡單的,先是將startValue和endValue強(qiáng)轉(zhuǎn)成Point對(duì)象驾霜,然后同樣根據(jù)fraction來計(jì)算當(dāng)前動(dòng)畫的x和y的值案训,最后組裝到一個(gè)新的Point對(duì)象當(dāng)中并返回。
這樣我們就將PointEvaluator編寫完成了粪糙,接下來我們就可以非常輕松地對(duì)Point對(duì)象進(jìn)行動(dòng)畫操作了强霎,比如說我們有兩個(gè)Point對(duì)象,現(xiàn)在需要將Point1通過動(dòng)畫平滑過度到Point2蓉冈,就可以這樣寫:

Point point1 = new Point(0, 0);  
Point point2 = new Point(300, 300);  
ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), point1, point2);  
anim.setDuration(5000);  
anim.start(); 

代碼很簡單城舞,這里我們先是new出了兩個(gè)Point對(duì)象,并在構(gòu)造函數(shù)中分別設(shè)置了它們的坐標(biāo)點(diǎn)寞酿。然后調(diào)用ValueAnimator的ofObject()方法來構(gòu)建ValueAnimator的實(shí)例家夺,這里需要注意的是,ofObject()方法要求多傳入一個(gè)TypeEvaluator參數(shù)伐弹,這里我們只需要傳入剛才定義好的PointEvaluator的實(shí)例就可以了拉馋。
好的,這就是自定義TypeEvaluator的全部用法惨好,掌握了這些知識(shí)之后煌茴,我們就可以來嘗試一下如何通過對(duì)Point對(duì)象進(jìn)行動(dòng)畫操作,從而實(shí)現(xiàn)整個(gè)自定義View的動(dòng)畫效果日川。
新建一個(gè)MyAnimView繼承自View蔓腐,代碼如下所示:

public class MyAnimView extends View {  
  
    public static final float RADIUS = 50f;  
  
    private Point currentPoint;  
  
    private Paint mPaint;  
  
    public MyAnimView(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
        mPaint.setColor(Color.BLUE);  
    }  
  
    @Override  
    protected void onDraw(Canvas canvas) {  
        if (currentPoint == null) {  
            currentPoint = new Point(RADIUS, RADIUS);  
            drawCircle(canvas);  
            startAnimation();  
        } else {  
            drawCircle(canvas);  
        }  
    }  
  
    private void drawCircle(Canvas canvas) {  
        float x = currentPoint.getX();  
        float y = currentPoint.getY();  
        canvas.drawCircle(x, y, RADIUS, mPaint);  
    }  
  
    private void startAnimation() {  
        Point startPoint = new Point(RADIUS, RADIUS);  
        Point endPoint = new Point(getWidth() - RADIUS, getHeight() - RADIUS);  
        ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);  
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
            @Override  
            public void onAnimationUpdate(ValueAnimator animation) {  
                currentPoint = (Point) animation.getAnimatedValue();  
                invalidate();  
            }  
        });  
        anim.setDuration(5000);  
        anim.start();  
    }  
  
}  

基本上還是很簡單的,總共也沒幾行代碼龄句。首先在自定義View的構(gòu)造方法當(dāng)中初始化了一個(gè)Paint對(duì)象作為畫筆回论,并將畫筆顏色設(shè)置為藍(lán)色,接著在onDraw()方法當(dāng)中進(jìn)行繪制分歇。這里我們繪制的邏輯是由currentPoint這個(gè)對(duì)象控制的透葛,如果currentPoint對(duì)象不等于空,那么就調(diào)用drawCircle()方法在currentPoint的坐標(biāo)位置畫出一個(gè)半徑為50的圓卿樱,如果currentPoint對(duì)象是空僚害,那么就調(diào)用startAnimation()方法來啟動(dòng)動(dòng)畫。
那么我們來觀察一下startAnimation()方法中的代碼,其實(shí)大家應(yīng)該很熟悉了萨蚕,就是對(duì)Point對(duì)象進(jìn)行了一個(gè)動(dòng)畫操作而已靶草。這里我們定義了一個(gè)startPoint和一個(gè)endPoint,坐標(biāo)分別是View的左上角和右下角岳遥,并將動(dòng)畫的時(shí)長設(shè)為5秒奕翔。然后有一點(diǎn)需要大家注意的,就是我們通過監(jiān)聽器對(duì)動(dòng)畫的過程進(jìn)行了監(jiān)聽浩蓉,每當(dāng)Point值有改變的時(shí)候都會(huì)回調(diào)onAnimationUpdate()方法派继。在這個(gè)方法當(dāng)中,我們對(duì)currentPoint對(duì)象進(jìn)行了重新賦值捻艳,并調(diào)用了invalidate()方法驾窟,這樣的話onDraw()方法就會(huì)重新調(diào)用,并且由于currentPoint對(duì)象的坐標(biāo)已經(jīng)改變了认轨,那么繪制的位置也會(huì)改變绅络,于是一個(gè)平移的動(dòng)畫效果也就實(shí)現(xiàn)了。
下面我們只需要在布局文件當(dāng)中引入這個(gè)自定義控件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    >  
  
    <com.example.tony.myapplication.MyAnimView  
        android:layout_width="match_parent"  
        android:layout_height="match_parent" />  
  
</RelativeLayout>  
效果

總結(jié):有時(shí)候大家可能對(duì)一些動(dòng)畫可能很沒有頭緒嘁字,也可能是一些屬性變化沒有什么頭緒恩急,希望鄙人上面所講的會(huì)對(duì)你有更大的幫助,你只要知道了思想才可能纪蜒,應(yīng)對(duì)更對(duì)的可能

注意:因?yàn)閷傩詣?dòng)畫是API3.0以后的屬性衷恭;所以在GitHub有大神給出來兼容的屬性動(dòng)畫:只要在AS里面依賴:

compile 'com.nineoldandroids:library:2.4.0'

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市纯续,隨后出現(xiàn)的幾起案子随珠,更是在濱河造成了極大的恐慌,老刑警劉巖杆烁,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異简卧,居然都是意外死亡兔魂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門举娩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來析校,“玉大人,你說我怎么就攤上這事铜涉≈遣#” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵芙代,是天一觀的道長吊奢。 經(jīng)常有香客問我,道長纹烹,這世上最難降的妖魔是什么页滚? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任召边,我火速辦了婚禮,結(jié)果婚禮上裹驰,老公的妹妹穿的比我還像新娘隧熙。我一直安慰自己,他們只是感情好幻林,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布贞盯。 她就那樣靜靜地躺著,像睡著了一般沪饺。 火紅的嫁衣襯著肌膚如雪躏敢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天随闽,我揣著相機(jī)與錄音父丰,去河邊找鬼。 笑死掘宪,一個(gè)胖子當(dāng)著我的面吹牛蛾扇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播魏滚,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼镀首,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鼠次?” 一聲冷哼從身側(cè)響起更哄,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎腥寇,沒想到半個(gè)月后成翩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赦役,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年麻敌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掂摔。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡术羔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出乙漓,到底是詐尸還是另有隱情级历,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布叭披,位于F島的核電站寥殖,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扛禽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一锋边、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧编曼,春花似錦豆巨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至熊户,卻和暖如春萍膛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嚷堡。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國打工蝗罗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝌戒。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓串塑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親北苟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子桩匪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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