代码艺术-Android针对带有复杂动画自定义view的代码设计

来源:互联网 发布:志鸿优化设计 编辑:程序博客网 时间:2024/05/19 14:51

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来说,代码结构会非常清晰,逻辑很很好把握。如果你有更好的方式,还望指教一下。

0 0