1. 程式人生 > >SurfaceView的入門(三)-----surfaceView繪製動畫切換圖片效果

SurfaceView的入門(三)-----surfaceView繪製動畫切換圖片效果

轉載: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);
    }

效果圖: