編輯:關於Android編程
源代碼及demo
先看看Win10的加載動畫(找了很久才找到):
每次打開電腦都會有這個加載動畫,看上挺cool的,就想著自己能否實現它。
要實現這個動畫?
首先想能否通過自定義SurfaceView控件(界面刷新是通過子線程來完成)來實現。這需要知道某一刻時間,那些小圓點在什麼位置。小圓點都在做圓周運動,可以看出除了左上角,可以通過勢能和動能的相互轉化來計算速度。但速度是變化的,如何計算某一個時刻的位置?網上一查,暈,都是微積分,算了吧。
後來,還是使用動畫吧,最後的效果:
動起來:
要玩動畫,自然就得理解動畫的核心部分。如果理解了,就坐電梯直達“動畫分析”。
一般復雜動畫需要自定義TimeInterpolator和TypeEvaluator,前者控制運動的速度,後者控制運動的軌跡。
TypeEvaluator不僅控制運動軌跡,只要有權限且能體現效果的setter屬性,都可以控制,如旋轉、縮放、顏色等;TimeInterpolator能干的事情,它也能干,只是為了方便,把它抽出來了。
這是他倆的關系(詳見參考5):
TimeInterpolator,名為時間插值器(或時間校正器),用於校正動畫播放的時間。默認是加速減速插值器AccelerateDecelerateInterpolator。
正常情況下,動畫在執行時間duration內,從起點到終點,中間是勻速運動,每一時刻都對應著固定的位置。為了統一,把時間[0, duration]轉換成時間百分比[0, 1],如duration=100ms時,在50ms,應該對應著時間比0.5,且位置在正中間。如下圖紅色線:
說明:
橫軸是實際運行的時間百分比軸(X軸),縱軸是校正後的時間百分比軸(Y軸); 圖中紫色線是經過校正後的時間百分比,在x=0.5時,正常情況是y=0.35,但校正後y不到0.3,也就是說這個時刻所在的位置還不到總路線的1/3。說白了,導數就是速度,紫色線的導數在逐漸變大,表示速度也在逐漸變快,這就是一個加速過程。 X軸是實際運行的時間軸,與Y軸,只有一對一、或一對多的關系,不能出現多對一的情況。一對多的關系就是來回運動的具體體現。再看TimeInterpolator,是個接口,只有一個方法getInterpolation(float input),方法中的參數對應著X軸,返回值對應著Y軸。
public interface TimeInterpolator {
float getInterpolation(float input);
}
3.2 TypeEvaluator
TypeEvaluator就是一個估值器。拿代碼說來,明白一點。
public interface TypeEvaluator {
public T evaluate(float fraction, T startValue, T endValue);
}
也是一個接口,有一個方法
evaluate(float fraction, T startValue, T endValue),參數說明:
fraction:時間插值器的校正值 startValue:開始值 endValue:結束值 T:可以是float類的單值,也可以是坐標、顏色等
一般與AnimatorUpdateListener的onAnimationUpdate()方法結合。
3.3 貝塞爾曲線
以下用到了很多二階貝塞爾曲線,具體計算公式如下(詳見參考2):
原理:由 P0 至 P1 的連續點 Q0,描述一條線段。
由 P1 至 P2 的連續點 Q1,描述一條線段。
由 Q0 至 Q1 的連續點 B(t),描述一條二次貝塞爾曲線。
經驗:P1-P0為曲線在P0處的切線
另外加兩條經驗:
為了更自然,P1-P2一般情況下也是曲線在P2處的切線,這樣就能算出P1的具體位置 曲線上每個點的坐標x和y,x和y分別套用此公式
3.4 效果比較
無圖無真相。。。圖來了
在起點、終點、運行時間都一樣的情況下,三種效果比較:
普通動畫——默認插值器是加速減速插值器AccelerateDecelerateInterpolator 自定義插值器動畫——速度效果是先勻速,再做貝塞爾曲線運動(先反向減速後,再正向加速)。如下圖紅線(其他畫圖軟件都沒不好辦,這時還是PS的鋼筆工具好用)
自定義估值器動畫——插值器是默認的(水平方向與普通動畫是一致的),做正弦曲線運動
三種動畫的代碼:
private static final long ANIM_DURATION = 5000;
/**
* 普通動畫
* 差值器默認為AccelerateDecelerateInterpolator
*/
private void normalAnim() {
ObjectAnimator oa = ObjectAnimator.ofFloat(v_normal, "translationX", 0, 300);
oa.setDuration(ANIM_DURATION);
oa.setRepeatCount(ValueAnimator.INFINITE);
oa.start();
}
/**
* 自定義插值器的動畫
*/
private void interpolatorAnim() {
ObjectAnimator oa = ObjectAnimator.ofFloat(v_interpolator, "translationX", 0, 300);
oa.setInterpolator(new TimeInterpolator() {
/**
* 獲取插值器的值
* @param input 原生時間比值[0, 1]
* @return 校正後的值
*/
@Override
public float getInterpolation(float input) {
// 前半段時間為直線(勻速運動),後半段貝塞爾曲線(先反向)
if (input < 0.5) {
return input;
}
// 把貝塞爾曲線范圍[0.5, 1]轉換成[0, 1]范圍
input = (input - 0.5f) * (1 - 0) / (1 - 0.5f);
float tmp = 1 - input;
return tmp * tmp * 0.5f + 2 * input * tmp * 0 + input * input * 1;
}
});
oa.setDuration(ANIM_DURATION);
oa.setRepeatCount(ValueAnimator.INFINITE);
oa.start();
}
/**
* 自定義估值器的動畫
*/
private void evaluatorAnim() {
ValueAnimator va = ValueAnimator.ofObject(
new TypeEvaluator() {
/**
* 估算結果
*
* @param fraction 由插值器提供的值,∈[0, 1]
* @param startValue 開始值
* @param endValue 結束值
* @return
*/
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
PointF p = new PointF();
float distance = endValue.x - startValue.x;
p.x = fraction * distance;
float halfDistance = distance / 2;
float sinX = (float) Math.sin(fraction * Math.PI / 0.5);
p.y = -halfDistance * sinX;
return p;
}
},
new PointF(0, 0),
new PointF(300, 0)
);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF pointF = (PointF) animation.getAnimatedValue();
v_evaluator.setTranslationX(pointF.x);
v_evaluator.setTranslationY(pointF.y);
}
});
va.setDuration(ANIM_DURATION);
va.setRepeatCount(ValueAnimator.INFINITE);
va.start();
}
1 安裝as的下載as官網下載地址為:http://developer.android.com/sdk/installing/studio.html國內鏡像網址&mdas
近期看了一堂某在線IT學習的視頻公開課,這裡就不說名字了,省的有打廣告的嫌疑。講到了利用HorizontalScrollView仿ViewPager設計的一個簡單相冊。其
360奇酷手機采用了雙卡槽雙卡設計,支持雙卡雙待。那麼360奇酷手機怎麼裝手機卡?下面小編為大家帶來奇酷手機sim卡/TF卡安裝教程。360奇酷手機三個版本
Drawable的簡介Android中包含了很多的Drawable,Drawable可以是一張圖片,同時也可以是顏色構造的圖形,因此在Drawable有時候沒有大小的分別