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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值