程式碼藝術-Android針對帶有複雜動畫自定義view的程式碼設計
阿新 • • 發佈:2019-01-08
Android自定義view有時需要完成一些複雜的動畫,這時後會發現程式碼看起來還是蠻複雜的,如何實現讓程式碼結構清晰,對提供程式碼穩定性以及對程式碼修改有著非常大的幫助。下面是我提供的一種思路。
思路原理: 我們知道一個動畫其實是有固定流程的,比如一個走動的小人,他先從左往右走,然後跳一下,然後從左往右走。這時我們可以把這個動畫劃分為三個小流程:1.左往右走。2.跳一下。3.右往左走。 三個流程依次執行,執行完上一個就到下一個。所以整個設計思路就是:流程劃分、流程控制。
原理是這樣,下面通過程式碼來實現一個比較帥的載入動畫,效果如下:
這個是個載入控制元件動畫,主要包含了兩個方法,一個是顯示show,一個是隱藏hide,show時有它顯示時的動畫效果,hide時有它的動畫效果,所以我們分別對這兩個動畫效果進行流程劃分。
show時的動畫:
這個動畫我劃分了兩個流程:1.執行載入動畫前顯示。2.執行載入動畫。
@Override
public void onShow() {
loadingState = LoadingState.show;
mShowController.clearProcess();
canceltimer();//清除之前的動畫
//新增流程1,執行動畫前顯示八個小球介面
mShowController.addProcess(new ShowProcess1(mShowController));
//新增流程2執行載入動畫
mShowController.addProcess(new ShowProcess2(mShowController));
mShowController.start();
postInvalidate();
}
可以看到,這時程式碼結構就非常清晰,如果這個動畫需要改動,只需要增刪改想要的流程就可以了。
上面的程式碼中的mShowController是顯示show動畫的流程控制器,它的作用是對新增的流程就行控制與管理。在view的onDraw的方法裡面把canvas傳入給當前執行的流程,就可以指定只讓當前的流程進行重新整理了。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (loadingState) {
case show:
mShowController.canvas = canvas;
//重新整理當前流程
mShowController.inValid(canvas);
break;
case hide:
mHideController.canvas = canvas;
mHideController.inValid(canvas);
break;
case resume:
mResumeController.canvas = canvas;
mResumeController.inValid(canvas);
break;
default:
break;
}
下面看看流程ShowProcess1 的程式碼:
/**
* @author bifan 第一個,初始化介面
*
*/
private class ShowProcess1 extends CanvaProcess {
public ShowProcess1(CanvaProcessController processController) {
super(processController);
}
@Override
public void inValid(Canvas canvas) {
//view重新整理時,如果當前流程是這個,就會呼叫到這個方法,在這裡執行當前流程的介面操作。
canvas.drawColor(Bgcolor);
initBallSize();
drawLoadingBitmap(canvas, 0);
NextProcess();
}
@Override
public void startProcess() {
//執行該流程時呼叫該方法,進行初始化操作或者啟動動畫等
}
@Override
public void release() {
}
}
在看看ShowProcess2 流程2:
/**
* @author bifan 第一個,執行載入動畫
*
*/
private class ShowProcess2 extends CanvaProcess {
public ShowProcess2(CanvaProcessController processController) {
super(processController);
}
@Override
public void inValid(Canvas canvas) {
canvas.drawColor(Bgcolor);//畫出背景顏色
drawLoadingBitmap(canvas, Rotatedegree);//畫出小球
}
@Override
public void startProcess() {
//啟動動畫
startloadinganimation();
}
@Override
public void release() {
}
}
private void startloadinganimation() {//通過Timer實現動畫
canceltimer();
mTimer = new Timer();
float br = Ballradius;
int nums;// 鋪滿的圓個數
float angle;
long fretime;
if (br > 0 && Loadingradius > 0) {
angle = (float) (Math.toDegrees(Math.asin(br / Loadingradius))) * 2;
} else {
angle = 360 / 8 / 2;
}
nums = (int) (360 / 8 / angle);
fretime = 1000 / 25 / nums;
final float anglec = angle;
mTimer.schedule(new TimerTask() {
@Override
public void run() {
Rotatedegree = Rotatedegree + anglec;
postInvalidate();
}
}, 200, fretime);
}
**
hide時的動畫:
**
這個動畫劃分了5個流程,具體如下:
@Override
public void onHide() {
loadingState = LoadingState.hide;
mShowController.clearProcess();
mHideController.clearProcess();
canceltimer();
//流程1:隱藏時介面初始化
mHideController.addProcess(new HideProcess1(mHideController));
//流程2:介面小球向外擴充套件動畫
mHideController.addProcess(new HideProcess2(mHideController));
//流程3:介面小球向內收縮
mHideController.addProcess(new HideProcess3(mHideController));
//流程4:小球收縮到中心時的一個動畫效果
mHideController.addProcess(new HideProcess4(mHideController));
//流程5:讓介面以圓的範圍擴充套件可見
mHideController.addProcess(new HideProcess5(mHideController));
mHideController.start();
postInvalidate();
}
具體各個流程的詳細程式碼就不貼了。
小結:可以明顯的看到,這種按流程劃分的程式碼設計,對於帶有很複雜的動畫效果的自定義viwe來說,程式碼結構會非常清晰,邏輯很很好把握。如果你有更好的方式,還望指教一下。