昨天在郭神的公眾號(hào)推送里看到了一篇關(guān)于小球自由落體動(dòng)畫加載控件的文章推送,就琢磨著班門弄斧做一個(gè)小球自由落體動(dòng)畫丰嘉,適合剛接觸自定義View和動(dòng)畫的童鞋學(xué)習(xí)夯到。
1.知識(shí)儲(chǔ)備
1.1自定義View
我們知道自定義View主要涉及兩個(gè)過(guò)程,測(cè)量和繪制饮亏,也就是簡(jiǎn)單地重寫onMeasure()(不過(guò)只需要在寬高設(shè)定為wrap-content時(shí)重寫)和onDraw()方法耍贾,接下來(lái)就自由發(fā)揮畫出自己想要的效果,詳細(xì)的方法可以參照我的初探自定義View(一)和初探自定義View(二)路幸。
1.2自定義動(dòng)畫
自定義動(dòng)畫涉及的方法也是主要就兩個(gè):
1.2.1applyTransformation(float interpolatedTime, Transformation t)
這個(gè)方法是自定義動(dòng)畫的核心方法荐开,定義了動(dòng)畫進(jìn)行的整個(gè)過(guò)程。第一個(gè)參數(shù)interpolatedTime是插值器的時(shí)間因子(可以理解成物理中的加速度)简肴,決定了這個(gè)動(dòng)畫從開(kāi)始到結(jié)束完成過(guò)程中的加速度晃听,第二個(gè)參數(shù)Transformation是矩陣的封裝類,一般使用這個(gè)類來(lái)獲得當(dāng)前的矩陣對(duì)象(當(dāng)前操作的View),然后對(duì)該對(duì)象進(jìn)行操作就能實(shí)現(xiàn)各種動(dòng)畫效果。
1.2.2initialize(int width, int height, int parentWidth, int parentHeight)
這個(gè)方法主要是通過(guò)覆寫父類的initialize()來(lái)進(jìn)行一些初始化工作。
2.實(shí)現(xiàn)過(guò)程
2.1小球的繪制
public void init(){
//初始化
mCirclePaint=new Paint();
mCirclePaint.setColor(Color.RED);
mCirclePaint.setStyle(Paint.Style.FILL);
}
//繪制
public void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawCircle(x,y,r,mCirclePaint);
}
@Override
protected void onSizeChanged(int w,int h,int oldW,int oldH){
super.onSizeChanged(w,h,oldW,oldH);
length = w; //這里的w指的是在xml文件中設(shè)定的寬度width的值
//確定圓心坐標(biāo)和半徑
x = length/2;
y = length/8;
r = (float) (length*0.5/8);
}
添加到布局文件中:
<com.example.animation.Ball
android:id="@+id/ball"
android:layout_width="400dp"
android:layout_height="400dp" />
經(jīng)過(guò)上述過(guò)程小球就畫好了能扒,如圖:
2.2動(dòng)畫效果的實(shí)現(xiàn)
public class OpenGL extends Animation {
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
setDuration(2000);// 設(shè)置默認(rèn)時(shí)長(zhǎng)
setFillAfter(true);// 動(dòng)畫結(jié)束后保留狀態(tài)
setInterpolator(new BounceInterpolator());// 設(shè)置插值器
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final Matrix matrix = t.getMatrix();
matrix.preTranslate(0,700 * interpolatedTime);
}
}
首先覆寫父類的initialize()方法進(jìn)行初始化setInterpolator(new BounceInterpolator());
這個(gè)方法是這個(gè)實(shí)現(xiàn)自由落體效果的關(guān)鍵佣渴,BounceInterpolator這個(gè)插值器的取值為0-1,而且從0變到1的速度越來(lái)越快赫粥,可以理解成物理場(chǎng)景中的勻加速運(yùn)動(dòng),而且在結(jié)束后還有一個(gè)彈跳的效果予借。
更多插值器效果
matrix.preTranslate(0,1000 * interpolatedTime);
這個(gè)可以理解成View的實(shí)時(shí)坐標(biāo)(x,y)越平,注意這里的x其實(shí)是Δx,表示View在移動(dòng)前的坐標(biāo)和移動(dòng)過(guò)程中的差值,0就代表這是一個(gè)豎直方向上的運(yùn)動(dòng)灵迫。
final OpenGL open=new OpenGL();
ball.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ball.startAnimation(open);
}
});
最后調(diào)用這個(gè)動(dòng)畫類的實(shí)例就能實(shí)現(xiàn)這一效果: