SurfaceView的入門(三)-----surfaceView繪製動畫切換圖片效果
阿新 • • 發佈:2018-11-12
轉載:https://blog.csdn.net/wangpeiming110/article/details/74638916
原始碼下載
前言:
之前在SurfaceView(一)中提到了SurfaceView的基礎實現,然後現在在那個基礎之上,開始使用SurfaceView來進行的動畫的實現。
SurfaceView的畫圖部分
private volatile boolean isPause; private boolean isFirst; @Override public void run() { while (mIsDrawing) { if (isPause) { } else { if (isFirst) { animManager.updateStartTime(); isFirst=false; } animManager.draw(); } } } public void setPause(boolean isPause) { if(isPause)isFirst=true; this.isPause = isPause; }
由於避免重複,之前的那些初始化步驟省略了,詳細的可以下面:
surfaceView(入門一):https://blog.csdn.net/qq_35014796/article/details/80783357
具體的動畫實現邏輯:
百葉窗效果:
private Path path = new Path(); private float bailine = 5;//百葉窗的行數 private int sum; private void AnimBaiYeChuang() { path.reset(); for (int i = 0; i < bailine; i++) { float top = height / bailine * i;//height:螢幕的高度 bailine: 百葉窗的行數 float bottom = top + height / bailine * rate;//rate 比率 0-1之間的值 float型別 path.addRect(0, top, width, bottom, Path.Direction.CW);//路徑新增畫的矩形 } mCanvas.clipPath(path);//按路徑進行裁剪 index=index%bitmaps.size();//圖片的索引 Log.i(TAG, "AnimBaiYeChuang: "+sum++);//呼叫了45次 mCanvas.drawBitmap(bitmaps.get(index), null, rect, paint);//畫布進行圖片的畫質 initAnim(1); }
階梯動畫效果:
private int timeInterval = 200;//每一行階梯與上一行起跑時間差 private int lineNum=4;//有多少個階梯 private float timePerLine = animtime - (timeInterval * (lineNum - 1));//為了保證最後一個階梯能夠佔滿寬度,我們要得出第一個佔滿寬度的時間 public void AnimJieTi(){ path.reset(); /* * 原本是 width-(rate*animtime)/animtime*width;這樣子得出的是動畫時間內left座標的位置 * 但是這個樣子並沒有階梯分層的效果,要有效果就要引入當前階梯行數(i)和timeIntervald的關係 * 所以更改為 (rate * animtime - i * timeInterval)/animtime * 然後上面因為新增i*timeInterva所以在原來的基礎上也要改的 * 上面說了timePerLine,為第一個階梯佔滿寬度的時間,所以更改為 * (rate * animtime - i * timeInterval) / timePerLine * * */ float left1 = width - (rate * animtime - 0 * timeInterval) / timePerLine * width;// float top1 = height / lineNum * 0; float right1 = width; float bottom1 = top1 + height / lineNum; path.addRect(left1, top1, right1, bottom1, Path.Direction.CW); //計算每一行需要展示的左上右下 for (int i = 1; i < lineNum; i++) { float left = width - (rate * animtime - i * timeInterval) / timePerLine * width; Log.i(TAG, "AnimJieTi: left: "+left); float top = height / lineNum * i; float right = width; float bottom = top + height / lineNum; path.addRect(left, top, right, bottom, Path.Direction.CW); } mCanvas.clipPath(path); index=index%bitmaps.size(); mCanvas.drawBitmap(bitmaps.get(index), null, rect, paint); initAnim(2); }
棋盤效果:
int rowNum = 9;//一行有多少個格子
int colNum = 6;//一列有多少個格子
public void AnimQiPan() {
path.reset();
//根據行數和列數計算每一個格子區域,最後剪切出棋盤區域
for (int i = 0; i < rowNum; i++) {
//單數行沒有問題,雙數行要從第一行-1行和第一行的第一個格子和第三個格子之間開始,除以2是為了配合第二行的第一個格子只佔用原來的一半
float leftStart = i % 2 == 0 ? 0 : -(width / colNum) / 2;
for (int j = 0; j < colNum+1 ; j++) {//這裡加1因為雙數行有比原來多一個
float left = leftStart + j * width / colNum;
float top = height / rowNum * i;
float right = left + width / colNum * rate;
float bottom = top + height / rowNum;
path.addRect(left, top, right, bottom, Path.Direction.CW);
}
}
mCanvas.clipPath(path);
index=index%bitmaps.size();
mCanvas.drawBitmap(bitmaps.get(index), null, rect, paint);
initAnim(3);
}
隨機線條效果:
int restNum;//剩餘數量的,用於隨機線條一開始是高度-1
Random random = new Random();//用於隨機線條和溶解
int[] lines;//這個是高的值
public void AnimSuiJiXian() {
path.reset();
//計算這一次需要取得的線條數量
int needNum = (int) ((height - 1) * rate - (height - 1 - restNum));
//迴圈隨機獲取線條陣列中的線條
//新加的
for (int i = 0; i < needNum; i++) {
//獲取到一條隨機線條,新增進path中
int r = random.nextInt(restNum - i);
path.addRect(0, lines[r], width, lines[r] + 1, Path.Direction.CW);
//保證之後再r中渠道的線段不是已經用過的
int temp = lines[r];
lines[r] = lines[restNum - i - 1];
lines[restNum - 1 - i] = temp;
}
//以前的
//遍歷陣列中“之前已取”的線條,全部放在path中
for (int i = 0; i < (height - 1) - restNum; i++) {
path.addRect(0, lines[(int) (height - 2 - i)], width, lines[(int) (height - 2 - i)] + 1, Path.Direction.CW);
}
//剩餘線條數量
restNum = restNum - needNum;
mCanvas.clipPath(path);
index=index%bitmaps.size();
mCanvas.drawBitmap(bitmaps.get(index), null, rect, paint);
initAnim(0);
}