自定义ProgressBar 模仿极客学院App的加载控件

效果图:



思路:

分为两种类型:

一种是两个球循环切换位置,另一种是四个球成对角移动,

1.初始化参数 : onMeasure方法计算控件的高和宽,然后初始化球的直径(四个球一样大),初始化四个球 或 两个球的中心点坐标,再计算球间的距离

再初始化ValueAnimator,和四个球的画笔。

2.动画效果:通过ValueAnimator的updateListener获取0.0F---1.0F之间的变化值value,根据value值不断去ondraw,来绘制每个球的位置。注意两个球的时候上下位置会发生变化,需要做个判断。


public class BallProgressView extends View {

    private int style; //
    public static final int TWO_BALL_STYLE = 2;
    public static final int FOUR_BALL_STYLE = 4;

    private int MAX_BALL_SIZE; //球的最大值
    private int MIN_BALL_SIZE; //球的最小值
    private int HEIGHT;  //自己的高度
    private int WIDTH;  //自己的宽度
    private float lengthOfTwoBall;  //两个球的距离

    private Paint firstBallPaint;  //第一个球的画笔
    private Paint secondBallPaint; //第二个球的画笔

    private float firstBallSize;  //第一个球的大小
    private float secondBallSize; //第二个球的大小
    private float firstBallX;  //第一个球的中心点
    private float firstBallY;
    private float secondBallX;  //第二个球的中心点
    private float secondBallY;

    private ValueAnimator valueAnimator;  //动画
    private float preValue;  //之前的值
    private float value;  //现在的值
    private boolean isFirstBallTop = true;  //是否是第一个球最上面显示
    private long duration;


    private float coorBalls[][]; //四个球的坐标
    private Paint thirdPaint;
    private Paint fourthPaint;


    public BallProgressView(Context context) {
        super(context);
        style = TWO_BALL_STYLE; //默认风格
    }

    public BallProgressView(Context context, AttributeSet attrs) {
        super(context, attrs);
        style = TWO_BALL_STYLE; //默认风格
    }

    public BallProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        style = TWO_BALL_STYLE; //默认风格
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        WIDTH = getMeasuredWidth();
        HEIGHT = getMeasuredHeight();
        System.out.println("width = " + WIDTH + " height = "  + HEIGHT);
        MAX_BALL_SIZE = WIDTH/5;
        MIN_BALL_SIZE = WIDTH/6;
        init();
    }

    private void init() {
        secondBallSize = firstBallSize = (MAX_BALL_SIZE + MIN_BALL_SIZE)/2;
        lengthOfTwoBall = WIDTH - firstBallSize;
        //两个球中心点坐标
        firstBallX = MAX_BALL_SIZE/2;
        firstBallY = secondBallY = HEIGHT/2;
        secondBallX = WIDTH - firstBallX;
        //四个球中心点坐标
        coorBalls = new float[4][2];
        coorBalls[0][0] = MAX_BALL_SIZE/2;
        coorBalls[0][1] = MAX_BALL_SIZE/2;
        coorBalls[1][0] = MAX_BALL_SIZE/2 + lengthOfTwoBall;
        coorBalls[1][1] = MAX_BALL_SIZE/2;
        coorBalls[2][0] = MAX_BALL_SIZE/2;
        coorBalls[2][1] = MAX_BALL_SIZE/2 + lengthOfTwoBall;
        coorBalls[3][0] = MAX_BALL_SIZE/2 + lengthOfTwoBall;
        coorBalls[3][1] = MAX_BALL_SIZE/2 + lengthOfTwoBall;
        initPaint();
        duration = 1000;
        initAnimator();
    }

    private void initPaint() {
        firstBallPaint = new Paint();
        firstBallPaint.setAntiAlias(true);
        firstBallPaint.setColor(getResources().getColor(R.color.green_01));

        secondBallPaint = new Paint();
        secondBallPaint.setAntiAlias(true);
        secondBallPaint.setColor(getResources().getColor(R.color.yellow));

        thirdPaint = new Paint();
        thirdPaint.setAntiAlias(true);
        thirdPaint.setColor(getResources().getColor(R.color.blue_01));

        fourthPaint = new Paint();
        fourthPaint.setAntiAlias(true);
        fourthPaint.setColor(getResources().getColor(R.color.red_01));

    }

    private void initAnimator() {
        preValue = value = 0f;
        valueAnimator = ValueAnimator.ofFloat(0f, 1f, 0f);
        valueAnimator.setDuration(duration);
        valueAnimator.setRepeatCount(-1);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                value = (Float) animation.getAnimatedValue();
                if ((value - preValue) > 0)
                    isFirstBallTop = true;
                else if ((value - preValue) < 0) {
                    isFirstBallTop = false;
                }
                preValue = value;
                invalidate();
            }
        });
        valueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {

            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                isFirstBallTop = true;
            }
        });
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if(style == TWO_BALL_STYLE) {
            if (isFirstBallTop) {
                canvas.drawCircle(secondBallX - (lengthOfTwoBall * value), secondBallY, (secondBallSize / 2), secondBallPaint);
                canvas.drawCircle(firstBallX + (lengthOfTwoBall * value), firstBallY, (firstBallSize / 2), firstBallPaint);
            } else {
                canvas.drawCircle(firstBallX + (lengthOfTwoBall * value), firstBallY, (firstBallSize / 2), firstBallPaint);
                canvas.drawCircle(secondBallX - (lengthOfTwoBall * value), secondBallY, (secondBallSize / 2), secondBallPaint);
            }
        }
        if(style == FOUR_BALL_STYLE){
            canvas.drawCircle(coorBalls[0][0] + (lengthOfTwoBall * value), coorBalls[0][1] + (lengthOfTwoBall * value), (firstBallSize / 2), firstBallPaint);
            canvas.drawCircle(coorBalls[1][0] - (lengthOfTwoBall * value), coorBalls[1][1] + (lengthOfTwoBall * value), (secondBallSize / 2), secondBallPaint);
            canvas.drawCircle(coorBalls[2][0] + (lengthOfTwoBall * value), coorBalls[2][1] - (lengthOfTwoBall * value), (firstBallSize / 2), thirdPaint);
            canvas.drawCircle(coorBalls[3][0] - (lengthOfTwoBall * value), coorBalls[3][1] - (lengthOfTwoBall * value), (secondBallSize / 2), fourthPaint);
        }
    }

    public void startAnimation() {
        if(valueAnimator != null)
            valueAnimator.start();
    }

    public void cancleAnimation(){
        if(valueAnimator != null){
            valueAnimator.cancel();
        }
    }

    public void setBallColor(int firstBallColor, int secondBallColor){
        firstBallPaint.setColor(firstBallColor);
        secondBallPaint.setColor(secondBallColor);
        invalidate();
    }

    public void setStyle(int style){
        this.style = style;
    }

    public void setDuration(long duration){
        this.duration = duration;
        initAnimator();
    }
}

调用方式:

ballProgressView = (BallProgressView)findViewById(R.id.activity_login_ball_progress);
        ballProgressView.setStyle(BallProgressView.FOUR_BALL_STYLE);
        ballProgressView.setDuration(1500);

ballProgressView.startAnimation();





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值