Android高效率实现win8进度条效果,手把手教会你实现效果,项目中直接使用

转载请注明出处:http://blog.csdn.net/jakeyangchina/article/details/54413523
新的一年新的开始,2017年争取每个星期至少一篇技术博客,方便日后复习,今天实现win8进度条效果,好多app页面都能看到这样的效果,利用休息时间我也来实现此效果,分享给大家,共同进步。
录制效果不是很好,不过运行在手机上效果还是好的

按照惯例先展示效果图:

这里写图片描述

功能介绍:
开启页面时,有五个小圆球开始从左向右运动,先减速运动,再加速运动

思路分析:

  1. 绘制五个实心圆
  2. 给圆添加动画效果
  3. 依次给五个小球设置开启延时时间,延时时间倍速增长
  4. 自定义插值器,实现减速加速运动
  5. 开启动画,时刻更新位置绘制圆

这里需要注意:

这里使用属性动画:ObjectAnimator.ofFloat(this,”fourCircleRadius”,startPosition, endPosition);
参数一:指定给哪个对象添加动画效果
参数二:属性名(方法名)
参数三:开始的位置
参数四:结束的位置
这里要注意的是参数的值,查看系统源码得知,内部是通过反射获取到方法,getXX和setXX方法,参数三和参数四就是传给setXX方法,指定起始位和结束位置,系统内部自动按照插值器返回的值进行计算把值传给setXX方法,仿照系统源码在本类中定义setXX方法,在此方法中调用invalidate()方法,位置改变时刻更新绘制

还需要注意一个地方:小球运动的起始位置和结束位置,指定起始位和结束位置要超出屏幕,要不然运动起来很不美观

接下来展示重要代码,代码标注的很详细,可以下载源码

字段
    //布局文件的宽度
    private int width;
    //布局文件的高度
    private int height;
    //动画开始的位置,在屏幕之外
    private float startPosition = -20;
    //动画结束的位置,在屏幕之外,动态赋值
    private float endPosition;
    //给圆的位置初始化值,先从屏幕之外开始运动
    private float oneValue = startPosition;
    private float twoValue = startPosition;
    private float threeValue = startPosition;
    private float fourValue = startPosition;
    private float fiveValue = startPosition;
    //动画的延时时间
    private long delaye = 90;
    //动画运动的时间
    private int duration = 1500;
    //用于判断是否关闭页面,关闭动画
    private boolean isFinish = false;
    //首次运行,只允许运行一次
    private boolean isFirst = false;
    //创建第一个圆的画笔
    private Paint paintOneCircle;
    //创建第二个圆的画笔
    private Paint paintTwoCircle;
    //创建第三个圆的画笔
    private Paint paintThreeCircle;
    //创建第四个圆的画笔
    private Paint paintFourCircle;
    //创建第五个圆的画笔
    private Paint paintFiveCircle;
    //第一个圆的动画对象
    private ObjectAnimator oneCircleAnimator;
    //第二个圆的动画对象
    private ObjectAnimator twoCircleAnimator;
    //第三个圆的动画对象
    private ObjectAnimator threeCircleAnimator;
    //第四个圆的动画对象
    private ObjectAnimator fourCircleAnimator;
    //第五个圆的动画对象
    private ObjectAnimator fiveCircleAnimator;

这里定义了五个圆,五个画笔,也可以定义一个画笔,在这里略

init() 
    /**
     * 初始化
     */
    private void init() {
        //创建第一个圆的画笔
        paintOneCircle = new Paint();
        paintOneCircle.setAntiAlias(true);
        paintOneCircle.setColor(Color.BLUE);

        //创建第二个圆的画笔
        paintTwoCircle = new Paint();
        paintTwoCircle.setAntiAlias(true);
        paintTwoCircle.setColor(Color.BLUE);

        //创建第三个圆的画笔
        paintThreeCircle = new Paint();
        paintThreeCircle.setAntiAlias(true);
        paintThreeCircle.setColor(Color.BLUE);

        //创建第四个圆的画笔
        paintFourCircle = new Paint();
        paintFourCircle.setAntiAlias(true);
        paintFourCircle.setColor(Color.BLUE);

        //创建第五个圆的画笔
        paintFiveCircle = new Paint();
        paintFiveCircle.setAntiAlias(true);
        paintFiveCircle.setColor(Color.BLUE);

    }

这个方法是初始化画笔

onSizeChanged()方法
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if(!isFirst) {
            //执行一次
            isFirst = true;
            //获取布局宽度
            width = getWidth();
            //获取布局高度
            height = getHeight();
            //设置动画结束的位置,一定要在屏幕外结束
            endPosition = 20 + width;
            //初始化动画
            initAnima();
            //开启动画
            startAnima();
        }
    }

onSizeChanged这个方法当布局尺寸改变时会回调,在这里获取控件宽高,这里需要注意endPosition值,指结束位置要超出屏幕,要不然小球运动结束后效果不美观

initAnima() 
    /**
     * 初始化动画
     */
    private void initAnima() {
        //创建第一个动画
        oneCircleAnimator = ObjectAnimator.ofFloat(this, "oneCircleRadius", startPosition, endPosition);
        oneCircleAnimator.setDuration(duration);
        oneCircleAnimator.setStartDelay(delaye);
        oneCircleAnimator.setInterpolator(new MyTimeInterpolator());

        //创建第二个动画
        twoCircleAnimator = ObjectAnimator.ofFloat(this, "twoCircleRadius", startPosition, endPosition);
        twoCircleAnimator.setDuration(duration);
        twoCircleAnimator.setStartDelay(delaye*2);
        twoCircleAnimator.setInterpolator(new MyTimeInterpolator());

        //创建第三个动画
        threeCircleAnimator = ObjectAnimator.ofFloat(this, "threeCircleRadius", startPosition, endPosition);
        threeCircleAnimator.setDuration(duration);
        threeCircleAnimator.setStartDelay(delaye*3);
        threeCircleAnimator.setInterpolator(new MyTimeInterpolator());

        //创建第四个动画
        fourCircleAnimator = ObjectAnimator.ofFloat(this, "fourCircleRadius", startPosition, endPosition);
        fourCircleAnimator.setDuration(duration);
        fourCircleAnimator.setStartDelay(delaye*4);
        fourCircleAnimator.setInterpolator(new MyTimeInterpolator());

        //创建第五个动画
        fiveCircleAnimator = ObjectAnimator.ofFloat(this, "fiveCircleRadius", startPosition, endPosition);
        fiveCircleAnimator.setDuration(duration);
        fiveCircleAnimator.setStartDelay(delaye*5);
        fiveCircleAnimator.setInterpolator(new MyTimeInterpolator());
        fiveCircleAnimator.addListener(this);
    }

上面方法是初始化动画,这里需要注意设置每个小球的延时时间,为了让小球逐个运动,这样效果美观

startAnima() 
    /**
     * 开启动画
     */
    private void startAnima() {
        //isFinish用于判断是否退出,当退出时不允许在开启动画
        if(!isFinish) {
            oneCircleAnimator.start();
            twoCircleAnimator.start();
            threeCircleAnimator.start();
            fourCircleAnimator.start();
            fiveCircleAnimator.start();
        }
    }

这个刚发是开启动画

onDraw()
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画第一个圆
        canvas.drawCircle(oneValue,height/2,10,paintOneCircle);

        //画第二个圆
        canvas.drawCircle(twoValue,height/2,10,paintTwoCircle);

        //画第三个圆
        canvas.drawCircle(threeValue,height/2,10,paintThreeCircle);

        //画第四个圆
        canvas.drawCircle(fourValue,height/2,10,paintFourCircle);

        //画第五个圆
        canvas.drawCircle(fiveValue,height/2,10,paintFiveCircle);

    }

在这个方法中绘制五个小圆

   /**
     * 更新第一个圆的位置
     * @param value
     */
    private void setOneCircleRadius(float value) {
        this.oneValue = value;
        //更新绘制
        invalidate();
    }

    /**
     * 更新第二个圆的位置
     * @param value
     */
    private void setTwoCircleRadius(float value) {
        this.twoValue = value;
        //更新绘制
        invalidate();
    }

    /**
     * 更新第三个圆的位置
     * @param value
     */
    private void setThreeCircleRadius(float value) {
        this.threeValue = value;
        //更新绘制
        invalidate();
    }

    /**
     * 更新第四个圆的位置
     * @param value
     */
    private void setFourCircleRadius(float value) {
        this.fourValue = value;
        //更新绘制
        invalidate();
    }

    /**
     * 更新第五个圆的位置
     * @param value
     */
    private void setFiveCircleRadius(float value) {
        this.fiveValue = value;
        //更新绘制
        invalidate();
    }

上方这五个方法很重要,当开启动画时,ObjectAnimator.ofFloat(this,”fourCircleRadius”,startPosition, endPosition);五个动画就会调用对应的方法,通过第二个参数指定方法名,内部通过反射获取,要时刻调用invalidate();更新绘制位置

onAnimationEnd()这个方法是动画监听器中的方法
    @Override
    public void onAnimationEnd(Animator animation) {
        //当最后一个动画结束后,从新开启所有动画
        startAnima();
    }

上面方法是给最后 一个动画添加监听器,当最后一个动画运动结束时,从新开启运动,这里也可以使用另一种方法,就是给动画设置循环播放(大家可以试验)

    /**
     * 自定义插值器,实现小球减速加速运动效果
     */
    private class MyTimeInterpolator implements TimeInterpolator {

        @Override
        public float getInterpolation(float input) {
            //先减速,再加速
            return (float) (Math.asin(2 * input - 1) / Math.PI + 0.5);
        }
    }

这个方法是自定义插值器,实现小球运动的效果

这里MainActivity方法就不给列出了,详细下载Demo,代码里标注很详细

如果你觉得此文章对你有收获,那么就顶下,你的无意间的动作就是我写出好文章的动力,希望能够帮助到大家,共同进步

如果大家还有什么疑问,请在下方留言。

源码下载,请点击这里!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值