Android自定义菊花进度条

先说废话

这几天要做一个跟ios一样的菊花进度条,刚开始让UI切了一张图片,然后看看怎么转起来,发现android动画里没有这样的动画,毕竟菊花的每根线是只改变透明度,不改变位置的。最后想到了自定义控件。然后UI又改了样式,这个控件用不到了,写这里保存。
这个菊花口有点大啊,没办法,ui给的要求就是这样。有没有bug我不知道,因为没有经过线上的考验,但是至少思路是这么回事。
public class LoadingProgressBar extends ProgressBar {
    private static final String TAG = "LoadingProgressBar";

    public LoadingProgressBar(Context context) {
        super(context);
    }

    public LoadingProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        loadAttrs(context, attrs);
        initPaint();
    }

    public LoadingProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /*view的默认宽度*/
    private int mWidth;
    /*view的默认高度*/
    private int mHeight;
    /*线条粗细*/
    private int paintBold;
    /*线条长度*/
    private int lineLength;
    /*背景线条颜色*/
    private int bgPaintColor;
    /*上层线条颜色*/
//    private int beforePaintColor;
    /*进度文字颜色*/
    private int textColor;
    /*线条个数*/
    private int lines;
    /*背景画笔*/
    private Paint bgPaint;
    /*前景画笔*/
    private Paint bfPaint;
    /*进度文字画笔*/
    private Paint textPaint;
    /*当前下载进度*/
    private int progress;
    /*最大进度*/
    private int max;
    /*循环绘制*/
    private int circle;
    private Handler handler = new Handler();

    /**
     * 加载我们在attrs.xml文件的自定义的属性
     */
    private void loadAttrs(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.loading_progress);
        paintBold = array.getDimensionPixelSize(R.styleable.loading_progress_paintBold, 10);
        lineLength = array.getDimensionPixelSize(R.styleable.loading_progress_lineLength, 25);
        bgPaintColor = array.getColor(R.styleable.loading_progress_backgroundColor, Color.GRAY);
//        beforePaintColor = array.getColor(R.styleable.loading_progress_beforeColor, Color.YELLOW);
        lines = array.getInt(R.styleable.loading_progress_lines, 12);
        max = array.getInt(R.styleable.loading_progress_max, 100);
        progress = array.getInt(R.styleable.loading_progress_progress, 0);
//        textColor = array.getColor(R.styleable.loading_progress_textColor, Color.BLACK);
        array.recycle();
    }

    /**
     * 初始化画笔
     */
    private void initPaint() {
        bgPaint = new Paint();
        bgPaint.setColor(bgPaintColor);
        bgPaint.setAntiAlias(true);
        bgPaint.setStrokeWidth(paintBold);
        //使得画笔更加圆滑
        bgPaint.setStrokeJoin(Paint.Join.ROUND);
        bgPaint.setStrokeCap(Paint.Cap.ROUND);

//        bfPaint = new Paint();
//        bfPaint.setColor(beforePaintColor);
//        bfPaint.setAntiAlias(true);
//        bfPaint.setStrokeWidth(paintBold);
//        bfPaint.setStrokeJoin(Paint.Join.ROUND);
//        bfPaint.setStrokeCap(Paint.Cap.ROUND);

//        textPaint = new Paint();
//        textPaint.setColor(textColor);
//        textPaint.setAntiAlias(true);
//        textPaint.setTextAlign(Paint.Align.CENTER);
//        textPaint.setTextSize(40);
        circle = 0;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取view的宽度
        mWidth = getViewSize(100, widthMeasureSpec);
        //获取view的高度
        mHeight = getViewSize(100, heightMeasureSpec);
    }

    /**
     * 测量模式 表示意思
     * UNSPECIFIED 父容器没有对当前View有任何限制,当前View可以任意取尺寸
     * EXACTLY 当前的尺寸就是当前View应该取的尺寸
     * AT_MOST 当前尺寸是当前View能取的最大尺寸
     *
     * @param defaultSize 默认大小
     * @param measureSpec 包含测量模式和宽高信息
     * @return 返回View的宽高大小
     */
    private int getViewSize(int defaultSize, int measureSpec) {
        int viewSize = defaultSize;
        //获取测量模式
        int mode = MeasureSpec.getMode(measureSpec);
        //获取大小
        int size = MeasureSpec.getSize(measureSpec);
        switch (mode) {
            case MeasureSpec.UNSPECIFIED: //如果没有指定大小,就设置为默认大小
                viewSize = defaultSize;
                break;
            case MeasureSpec.AT_MOST: //如果测量模式是最大取值为size
                //我们将大小取最大值,你也可以取其他值
                viewSize = size;
                break;
            case MeasureSpec.EXACTLY: //如果是固定的大小,那就不要去改变它
                viewSize = size;
                break;
        }
        return viewSize;
    }

    @Override
    protected void onDraw(Canvas canvas) {
//        super.onDraw(canvas);
        int x = mWidth / 2;
        int y = mHeight / 2;
        int r = x - 5;
        int alpha = 255;//范围0-255.
        for (int i = 0; i < lines; i++) {//从circle到circle+2最亮,其他依次减小

            //circle=0,亮2.1.0; circle =1,亮1.0.11; circle = 2,亮0.11.10; circle = 3,亮11.10.9; circle = 4,亮10.9.8;.....circle = 11,亮1.2.3
            switch (circle) {
                case 0:
                    if (i == 2 || i == 1 || i == 0) {
                        alpha = 255;
                    } else {
                        alpha = (int) (255 * (1 - 0.1 * (i + circle - 2)));//i=3,亮度0.9;i=4,亮度0.8....i=11亮度0.1
                    }
                    break;
                case 1:
                    if (i == 1 || i == 0 || i == 11) {
                        alpha = 255;
                    } else {
                        alpha = (int) (255 * (1 - 0.1 * (i + circle - 2)));//i=2,亮度0.9;i=3,亮度0.8....i=10亮度0.1
                    }
                    break;
                case 2:
                    if (i == 0 || i == 11 || i == 10) {
                        alpha = 255;
                    } else {
                        alpha = (int) (255 * (1 - 0.1 * (i + circle - 2)));//i=1,亮度0.9;i=4,亮度0.8....i=11亮度0.1
                    }
                    break;
                default:
                    if (i == 12 - circle + 0 || i == 12 - circle + 1 || i == 12 - circle + 2) {
                        alpha = 255;
                    } else {
                        alpha = (int) (255 * (1 - 0.1 * (i + circle - 2)));//i=1,亮度0.9;i=4,亮度0.8....i=11亮度0.1
                    }
                    break;
            }

            Log.e(TAG, "circle  =  " + circle + "    i=  " + i + "      ,    alpha=   " + alpha);
            bgPaint.setAlpha(alpha);
            canvas.drawLine(x, y - r, x, y - r + lineLength, bgPaint);
            canvas.rotate(-360 / lines, x, y);
        }

        circle++;
        if (circle == 12) {
            circle = 0;
        }


        handler.postDelayed(runnable, 50);
    }
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            invalidate();
        }
    };
    @Override
    protected void onDetachedFromWindow() {
        handler.removeCallbacks(runnable);
        super.onDetachedFromWindow();

    }

    /**
     * 为进度设置动画
     * ValueAnimator是整个属性动画机制当中最核心的一个类,属性动画的运行机制是通过不断地对值进行操作来实现的,
     * 而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。
     * 它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,
     * 我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,
     * 那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。
     *
     * @param start    开始值
     * @param current  结束值
     * @param duration 动画时长
     */
    public void startAnimation(int start, int current, int duration) {
        ValueAnimator progressAnimator = ValueAnimator.ofInt(start, current);
        progressAnimator.setDuration(duration);
        progressAnimator.setTarget(progress);
        progressAnimator.setInterpolator(new BounceInterpolator());
        progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                progress = (int) animation.getAnimatedValue();
                invalidate();
            }
        });
        progressAnimator.start();
    }

    /*设置进度最大值*/
//    public void setMax(int max) {
//        this.max = max;
//        invalidate();
//    }

    /*设置当前进度*/
//    public void setProgress(int progress) {
//        this.progress = progress;
//        invalidate();
//    }
}

//然后是使用

<com.hyphenate.easeui.widget.LoadingProgressBar
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:layout_centerInParent="true"
    loading_progress_:backgroundColor="#9f9c9c"
    loading_progress_:lineLength="10dp"
    loading_progress_:lines="12"
    loading_progress_:max="100"
    loading_progress_:paintBold="3dp"
    loading_progress_:progress="70" />
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值