package com.huawei.neteco.appclient.smartsite.ui.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; import android.util.AttributeSet; import android.view.View; import com.huawei.neteco.appclient.smartsite.R; /** * Created by chenliu on 2016/8/26.<br/> * 描述:添加圆角支持 on 2016/11/11 * </br> */ public class FlikerProgressBar extends View implements Runnable{ private PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP); private int DEFAULT_HEIGHT_DP = 35; private int borderWidth; private float maxProgress = 100f; private Paint textPaint; private Paint bgPaint; private Paint pgPaint; private String progressText; private Rect textRect; private RectF bgRectf; /** * 左右来回移动的滑块 */ private Bitmap flikerBitmap; /** * 滑块移动最左边位置,作用是控制移动 */ private float flickerLeft; /** * 进度条 bitmap ,包含滑块 */ private Bitmap pgBitmap; private Canvas pgCanvas; /** * 当前进度 */ private float progress; private boolean isFinish; private boolean isStop; /** * 下载中颜色 */ private int loadingColor; /** * 暂停时颜色 */ private int stopColor; /** * 进度文本、边框、进度条颜色 */ private int progressColor; private int textSize; private int radius; private Thread thread; BitmapShader bitmapShader; public FlikerProgressBar(Context context) { this(context, null, 0); } public FlikerProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FlikerProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(attrs); } private void initAttrs(AttributeSet attrs) { TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.FlikerProgressBar); try { textSize = (int) ta.getDimension(R.styleable.FlikerProgressBar_textSize, 12); loadingColor = ta.getColor(R.styleable.FlikerProgressBar_loadingColor, Color.parseColor("#000000")); stopColor = ta.getColor(R.styleable.FlikerProgressBar_stopColor, Color.parseColor("#000000")); radius = (int) ta.getDimension(R.styleable.FlikerProgressBar_radius, 0); borderWidth = (int) ta.getDimension(R.styleable.FlikerProgressBar_borderWidth, 1); } finally { ta.recycle(); } } private void init() { bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); bgPaint.setStyle(Paint.Style.STROKE); bgPaint.setStrokeWidth(borderWidth); pgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); pgPaint.setStyle(Paint.Style.FILL); textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); textPaint.setTextSize(textSize); textRect = new Rect(); bgRectf = new RectF(borderWidth, borderWidth, getMeasuredWidth() - borderWidth, getMeasuredHeight() - borderWidth); if(isStop){ progressColor = stopColor; } else{ progressColor = loadingColor; } flikerBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.flicker_1); flickerLeft = -flikerBitmap.getWidth(); initPgBimap(); } private void initPgBimap() { pgBitmap = Bitmap.createBitmap(getMeasuredWidth() - borderWidth, getMeasuredHeight() - borderWidth, Bitmap.Config.ARGB_8888); pgCanvas = new Canvas(pgBitmap); thread = new Thread(this); thread.start(); } @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 = dp2px(DEFAULT_HEIGHT_DP); break; case MeasureSpec.EXACTLY: case MeasureSpec.UNSPECIFIED: height = heightSpecSize; break; } setMeasuredDimension(widthSpecSize, height); if(pgBitmap == null){ init(); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //背景 drawBackGround(canvas); //进度 drawProgress(canvas); //进度text drawProgressText(canvas); //变色处理 drawColorProgressText(canvas); } /** * 边框 * @param canvas */ private void drawBackGround(Canvas canvas) { bgPaint.setColor(progressColor); //left、top、right、bottom不要贴着控件边,否则border只有一半绘制在控件内,导致圆角处线条显粗 canvas.drawRoundRect(bgRectf, radius, radius, bgPaint); } /** * 进度 */ private void drawProgress(Canvas canvas) { pgPaint.setColor(progressColor); float right = (progress / maxProgress) * getMeasuredWidth(); pgCanvas.save(Canvas.CLIP_SAVE_FLAG); pgCanvas.clipRect(0, 0, right, getMeasuredHeight()); pgCanvas.drawColor(progressColor); pgCanvas.restore(); if(!isStop){ pgPaint.setXfermode(xfermode); pgCanvas.drawBitmap(flikerBitmap, flickerLeft, 0, pgPaint); pgPaint.setXfermode(null); } //控制显示区域 bitmapShader = new BitmapShader(pgBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); pgPaint.setShader(bitmapShader); canvas.drawRoundRect(bgRectf, radius, radius, pgPaint); } /** * 进度提示文本 * @param canvas */ private void drawProgressText(Canvas canvas) { textPaint.setColor(progressColor); progressText = getProgressText(); textPaint.getTextBounds(progressText, 0, progressText.length(), textRect); int tWidth = textRect.width(); int tHeight = textRect.height(); float xCoordinate = (getMeasuredWidth() - tWidth) / 2; float yCoordinate = (getMeasuredHeight() + tHeight) / 2; canvas.drawText(progressText, xCoordinate, yCoordinate, textPaint); } /** * 变色处理 * @param canvas */ private void drawColorProgressText(Canvas canvas) { textPaint.setColor(Color.WHITE); int tWidth = textRect.width(); int tHeight = textRect.height(); float xCoordinate = (getMeasuredWidth() - tWidth) / 2; float yCoordinate = (getMeasuredHeight() + tHeight) / 2; float progressWidth = (progress / maxProgress) * getMeasuredWidth(); if(progressWidth > xCoordinate){ canvas.save(Canvas.CLIP_SAVE_FLAG); float right = Math.min(progressWidth, xCoordinate + tWidth * 1.1f); canvas.clipRect(xCoordinate, 0, right, getMeasuredHeight()); canvas.drawText(progressText, xCoordinate, yCoordinate, textPaint); canvas.restore(); } } public void setProgress(float progress){ if(!isStop){ if(progress < maxProgress){ this.progress = progress; } else { this.progress = maxProgress; finishLoad(); } invalidate(); } } public void setStop(boolean stop) { isStop = stop; if(isStop){ progressColor = stopColor; thread.interrupt(); } else { progressColor = loadingColor; thread = new Thread(this); thread.start(); } invalidate(); } public void finishLoad() { isFinish = true; setStop(true); } public void toggle(){ if(!isFinish){ if(isStop){ setStop(false); } else { setStop(true); } } } @Override public void run() { int width = flikerBitmap.getWidth(); try { while (!isStop && !thread.isInterrupted()){ flickerLeft += dp2px(5); float progressWidth = (progress / maxProgress) * getMeasuredWidth(); if(flickerLeft >= progressWidth){ flickerLeft = -width; } postInvalidate(); Thread.sleep(20); } }catch (InterruptedException e) { e.printStackTrace(); } } /** * 重置 */ public void reset(){ setStop(true); progress = 0; isFinish = false; isStop = false; progressColor = loadingColor; progressText = ""; flickerLeft = -flikerBitmap.getWidth(); initPgBimap(); } public float getProgress() { return progress; } public boolean isStop() { return isStop; } public boolean isFinish() { return isFinish; } private String getProgressText() { String text= ""; if(!isFinish){ if(!isStop){ text = "下载中" + progress + "%"; } else { text = "继续"; } } else{ text = "下载完成"; } return ""; } private int dp2px(int dp){ float density = getContext().getResources().getDisplayMetrics().density; return (int) (dp * density); } }
<declare-styleable name="FlikerProgressBar"> <attr name="textSize" format="dimension"/> <attr name="loadingColor" format="color"/> <attr name="stopColor" format="color"/> <attr name="radius" format="dimension"/> <attr name="borderWidth" format="dimension"/> </declare-styleable>