編輯:關於Android編程
在上篇文章中介紹補間動畫缺點的時候有提到過,補間動畫是只能對View對象進行動畫操作的。而屬性動畫就不再受這個限制,它可以對任意對象進行動畫操作。那麼大家應該還記得在上篇文章當中我舉的一個例子,比如說我們有一個自定義的View,在這個View當中有一個Point對象用於管理坐標,然後在onDraw()方法當中就是根據這個Point對象的坐標值來進行繪制的。也就是說,如果我們可以對Point對象進行動畫操作,那麼整個自定義View的動畫效果就有了。OK,下面我們就來學習一下如何實現這樣的效果。
在開始動手之前,我們還需要掌握另外一個知識點,就是TypeEvaluator的用法。可能在大多數情況下我們使用屬性動畫的時候都不會用到TypeEvaluator,但是大家還是應該了解一下它的用法,以防止當我們遇到一些解決不掉的問題時能夠想起來還有這樣的一種解決方案。
那麼TypeEvaluator的作用到底是什麼呢?簡單來說,就是告訴動畫系統如何從初始值過度到結束值。我們在上一篇文章中學到的ValueAnimator.ofFloat()方法就是實現了初始值與結束值之間的平滑過度,那麼這個平滑過度是怎麼做到的呢?其實就是系統內置了一個FloatEvaluator,它通過計算告知動畫系統如何從初始值過度到結束值,我們來看一下FloatEvaluator的代碼實現:
publicclassFloatEvaluatorimplementsTypeEvaluator{
publicObjectevaluate(floatfraction,ObjectstartValue,ObjectendValue){
floatstartFloat=((Number)startValue).floatValue();
returnstartFloat+fraction*(((Number)endValue).floatValue()-startFloat);
}
} 可以看到,FloatEvaluator實現了TypeEvaluator接口,然後重寫evaluate()方法。evaluate()方法當中傳入了三個參數,第一個參數fraction非常重要,這個參數用於表示動畫的完成度的,我們應該根據它來計算當前動畫的值應該是多少,第二第三個參數分別表示動畫的初始值和結束值。那麼上述代碼的邏輯就比較清晰了,用結束值減去初始值,算出它們之間的差值,然後乘以fraction這個系數,再加上初始值,那麼就得到當前動畫的值了。
好的,那FloatEvaluator是系統內置好的功能,並不需要我們自己去編寫,但介紹它的實現方法是要為我們後面的功能鋪路的。前面我們使用過了ValueAnimator的ofFloat()和ofInt()方法,分別用於對浮點型和整型的數據進行動畫操作的,但實際上ValueAnimator中還有一個ofObject()方法,是用於對任意對象進行動畫操作的。但是相比於浮點型或整型數據,對象的動畫操作明顯要更復雜一些,因為系統將完全無法知道如何從初始對象過度到結束對象,因此這個時候我們就需要實現一個自己的TypeEvaluator來告知系統如何進行過度。
下面來先定義一個Point類,如下所示:
publicclassPoint{
privatefloatx;
privatefloaty;
publicPoint(floatx,floaty){
this.x=x;
this.y=y;
}
publicfloatgetX(){
returnx;
}
publicfloatgetY(){
returny;
}
}
Point類非常簡單,只有x和y兩個變量用於記錄坐標的位置,並提供了構造方法來設置坐標,以及get方法來獲取坐標。接下來定義PointEvaluator,如下所示:
publicclassPointEvaluatorimplementsTypeEvaluator{
@Override
publicObjectevaluate(floatfraction,ObjectstartValue,ObjectendValue){
PointstartPoint=(Point)startValue;
PointendPoint=(Point)endValue;
floatx=startPoint.getX()+fraction*(endPoint.getX()-startPoint.getX());
floaty=startPoint.getY()+fraction*(endPoint.getY()-startPoint.getY());
Pointpoint=newPoint(x,y);
returnpoint;
}
} 可以看到,PointEvaluator同樣實現了TypeEvaluator接口並重寫了evaluate()方法。其實evaluate()方法中的邏輯還是非常簡單的,先是將startValue和endValue強轉成Point對象,然後同樣根據fraction來計算當前動畫的x和y的值,最後組裝到一個新的Point對象當中並返回。
這樣我們就將PointEvaluator編寫完成了,接下來我們就可以非常輕松地對Point對象進行動畫操作了,比如說我們有兩個Point對象,現在需要將Point1通過動畫平滑過度到Point2,就可以這樣寫:
Pointpoint1=newPoint(0,0);
Pointpoint2=newPoint(300,300);
ValueAnimatoranim=ValueAnimator.ofObject(newPointEvaluator(),point1,point2);
anim.setDuration(5000);
anim.start(); 代碼很簡單,這裡我們先是new出了兩個Point對象,並在構造函數中分別設置了它們的坐標點。然後調用ValueAnimator的ofObject()方法來構建ValueAnimator的實例,這裡需要注意的是,ofObject()方法要求多傳入一個TypeEvaluator參數,這裡我們只需要傳入剛才定義好的PointEvaluator的實例就可以了。
好的,這就是自定義TypeEvaluator的全部用法,掌握了這些知識之後,我們就可以來嘗試一下如何通過對Point對象進行動畫操作,從而實現整個自定義View的動畫效果。
新建一個MyAnimView繼承自View,代碼如下所示:
publicclassMyAnimViewextendsView{
publicstaticfinalfloatRADIUS=50f;
privatePointcurrentPoint;
privatePaintmPaint;
publicMyAnimView(Contextcontext,AttributeSetattrs){
super(context,attrs);
mPaint=newPaint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
}
@Override
protectedvoidonDraw(Canvascanvas){
if(currentPoint==null){
currentPoint=newPoint(RADIUS,RADIUS);
drawCircle(canvas);
startAnimation();
}else{
drawCircle(canvas);
}
}
privatevoiddrawCircle(Canvascanvas){
floatx=currentPoint.getX();
floaty=currentPoint.getY();
canvas.drawCircle(x,y,RADIUS,mPaint);
}
privatevoidstartAnimation(){
PointstartPoint=newPoint(RADIUS,RADIUS);
PointendPoint=newPoint(getWidth()-RADIUS,getHeight()-RADIUS);
ValueAnimatoranim=ValueAnimator.ofObject(newPointEvaluator(),startPoint,endPoint);
anim.addUpdateListener(newValueAnimator.AnimatorUpdateListener(){
@Override
publicvoidonAnimationUpdate(ValueAnimatoranimation){
currentPoint=(Point)animation.getAnimatedValue();
invalidate();
}
});
anim.setDuration(5000);
anim.start();
}
} 基本上還是很簡單的,總共也沒幾行代碼。首先在自定義View的構造方法當中初始化了一個Paint對象作為畫筆,並將畫筆顏色設置為藍色,接著在onDraw()方法當中進行繪制。這裡我們繪制的邏輯是由currentPoint這個對象控制的,如果currentPoint對象不等於空,那麼就調用drawCircle()方法在currentPoint的坐標位置畫出一個半徑為50的圓,如果currentPoint對象是空,那麼就調用startAnimation()方法來啟動動畫。
那麼我們來觀察一下startAnimation()方法中的代碼,其實大家應該很熟悉了,就是對Point對象進行了一個動畫操作而已。這裡我們定義了一個startPoint和一個endPoint,坐標分別是View的左上角和右下角,並將動畫的時長設為5秒。然後有一點需要大家注意的,就是我們通過監聽器對動畫的過程進行了監聽,每當Point值有改變的時候都會回調onAnimationUpdate()方法。在這個方法當中,我們對currentPoint對象進行了重新賦值,並調用了invalidate()方法,這樣的話onDraw()方法就會重新調用,並且由於currentPoint對象的坐標已經改變了,那麼繪制的位置也會改變,於是一個平移的動畫效果也就實現了。
下面我們只需要在布局文件當中引入這個自定義控件:
android:layout_height="match_parent"
>
android:layout_width="match_parent"
android:layout_height="match_parent"/>
最後運行一下程序,效果如下圖所示:
今天給大家分享下關於修改MTK平台下系統首次開機的默認屏幕背光亮度,系統語言默認英語情況下修改日期格式,修改拍照屬性,具體修改的地方不清楚或者沒人告知的話,請參照之前幾篇
前言從事Android開發的小伙伴們,想必都會遇到這樣的問題。當你的應用中需要集成百度地圖、極光推送等第三方平台時,會去申請一個叫做AppKey的東西。與此同時,你得提供
在一些Android應用的開發中,需要通過JNI和Android NDK工具實現JAVA和C/C++之間的相互調用。Java Native Interface (JNI)
首先給大家看一下我們今天這個最終實現的效果圖: 這個是ios中的反彈效果。當然我們安卓中如果想要實現這種效果,感覺不會那麼生硬,滾動到底部或者頂部的時候。當然使