Android 仿应用宝下载进度条

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/u011102153/article/details/52367206

一、介绍

yyb

  1. 一个横向进度条
  2. 下载完成区域有一个滑块不断从左往右滑动(最开始就是被这个吸引的,就想着这个怎么实现的)
  3. 进度条中间显示当前进度,值得注意的是,进度条文本包含在下载区域中的部分显示为白色
  4. 点击暂停,进度条颜色改变,进度文本改变

二、分析

根据以上简单介绍,可以抓住要实现的重难点是上面的第2、3点。

 1. 进度条文本包含在下载区域中的部分显示为白色怎么实现?

这个和歌词变色的效果是一样的,所以实现原理应该差不多。canvas有一个save的方法,然后设置成CLIP_SAVE_FLAG标志,这个标志的解释是restore the current clip when restore() is called.然后结合canvas的clip方法和restore方法就能实现。后文见代码④。

   2.  下载完成区域有一个滑块不断从左往右滑动怎么实现?

首先想到的是画这样一个滑块(其实是一张图片),然后不断根据当前进度修改位置实现移动。需要注意的是这个滑块的移动特点: 滑块的右边界开始进入,最后左边界消失,而且只在下载完成这个区域内有显示(右边界超出下载完成右边界部分不显示)这让我想到两个图层重叠时的显示模式,再看看这幅图,那么这里就可以使用SRC_ATOP模式。

这里写图片描述

三、实现

1.自定义属性

<declare-styleable name="FlikerProgressBar">
    <attr name="textSize" format="dimension|reference"/>

    <attr name="loadingColor" format="color|reference"/>

    <attr name="stopColor" format="color|reference"/>

</declare-styleable>
private void initAttrs(AttributeSet attrs) {
    if (attrs != null) {
        TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.FlikerProgressBar);
        textSize = (int) ta.getDimension(R.styleable.FlikerProgressBar_textSize, dp2px(12));
        loadingColor = ta.getColor(R.styleable.FlikerProgressBar_loadingColor, Color.parseColor("#40c4ff"));
        stopColor = ta.getColor(R.styleable.FlikerProgressBar_stopColor, Color.parseColor("#ff9800"));
        ta.recycle();
    }
}

2.重写onMeasure方法,当height设置为wrap_content时设置为默认高度

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
    int height = 0;
    switch (heightSpecMode){
        case MeasureSpec.AT_MOST:
            height = (int) dp2px(DEFAULT_HEIGHT_DP);
            break;
        case MeasureSpec.EXACTLY:
        case MeasureSpec.UNSPECIFIED:
            height = heightSpecSize;
            break;
    }
    setMeasuredDimension(widthSpecSize, height);
}

3.重写onDraw方法

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    //1.边框
    drawBorder(canvas);

    //2.进度
    drawProgress();

    canvas.drawBitmap(pgBitmap, 0, 0, null);

    //3.进度text
    drawProgressText(canvas);

    //4.变色处理
    drawColorProgressText(canvas);
}

①绘制边框

private void drawBorder(Canvas canvas) {
    bgPaint.setStyle(Paint.Style.STROKE);
    bgPaint.setColor(progressColor);
    bgPaint.setStrokeWidth(dp2px(1));
    canvas.drawRect(0, 0, getWidth(), getHeight(), bgPaint);
}

②绘制进度

private void drawProgress() {
    bgPaint.setStyle(Paint.Style.FILL);
    bgPaint.setStrokeWidth(0);
    bgPaint.setColor(progressColor);

    float right = (progress / MAX_PROGRESS) * getMeasuredWidth();
    pgBitmap = Bitmap.createBitmap((int) Math.max(right, 1), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    pgCanvas = new Canvas(pgBitmap);
    pgCanvas.drawColor(progressColor);

    if(!isStop){
        bgPaint.setXfermode(xfermode);
        pgCanvas.drawBitmap(flikerBitmap, flickerLeft, 0, bgPaint);
        bgPaint.setXfermode(null);
    }
}

③绘制进度条显示文本

private void drawProgressText(Canvas canvas) {
    textPaint.setColor(progressColor);
    progressText = getProgressText();
    textPaint.getTextBounds(progressText, 0, progressText.length(), textBouds);
    int tWidth = textBouds.width();
    int tHeight = textBouds.height();
    float xCoordinate = (getMeasuredWidth() - tWidth) / 2;
    float yCoordinate = (getMeasuredHeight() + tHeight) / 2;
    canvas.drawText(progressText, xCoordinate, yCoordinate, textPaint);
}

④进度条文本变色处理

private void drawColorProgressText(Canvas canvas) {
    textPaint.setColor(Color.WHITE);
    int tWidth = textBouds.width();
    int tHeight = textBouds.height();
    float xCoordinate = (getMeasuredWidth() - tWidth) / 2;
    float yCoordinate = (getMeasuredHeight() + tHeight) / 2;
    float progressWidth = (progress / MAX_PROGRESS) * getMeasuredWidth();
    if(progressWidth > xCoordinate){
        canvas.save(Canvas.CLIP_SAVE_FLAG);
        float right = Math.min(progressWidth, xCoordinate + tWidth);
        canvas.clipRect(xCoordinate, 0, right, getMeasuredHeight());
        canvas.drawText(progressText, xCoordinate, yCoordinate, textPaint);
        canvas.restore();
    }
}

四、效果图

这里写图片描述

五、下载

下载:https://github.com/LineChen/FlickerProgressBar

猜你喜欢

转载自blog.csdn.net/u011102153/article/details/52367206
今日推荐