1. 程式人生 > >程式碼藝術-Android針對帶有複雜動畫自定義view的程式碼設計

程式碼藝術-Android針對帶有複雜動畫自定義view的程式碼設計

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來說,程式碼結構會非常清晰,邏輯很很好把握。如果你有更好的方式,還望指教一下。