package com.zhongjh.progresslibrary.widget; import android.content.Context; import android.content.res.TypedArray; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import com.zhongjh.progresslibrary.R; import java.util.ArrayList; /** * @author [email protected] * 一个在当前进度中心带图片和动画的ProgressBar */ public class PictureProgressBar extends View { private final String TAG = "PictureProgressBar"; //画笔 private Paint paintBackGround, paintBar; //颜色 private int backGroundColor = Color.GRAY, barColor = Color.RED; //图片 private Drawable drawable = null; //进度改变监听器 private OnProgressChangeListener onProgressChangeListener; //Drawable的宽高半径 private int halfDrawableWidth = 0, halfDrawableHeight = 0; //Drawable高度偏移量 private int drawableHeightOffset = 0; //是否为圆角 private boolean isRound = true; //圆角半轴 private int roundX = 20, roundY = 20; //进度值和最大值 private int progress = 0, max = 100; //进度条百分比 private float progressPercentage = 0; //进度条当前进度中心点 private int x, y; //是否令设进度条宽高 private boolean isSetBar = false; //进度条宽高 private int progressWidth = 100, progressHeight = 30; //进度条高度偏移量 private int progressHeightOffset = 0; // //进度条开始结束位置padding // private int paddingStart = 10,paddingEnd = 0; //进度条刷新时间 private int refreshTime = 50; private RectF rectFBG = new RectF(), rectFPB = new RectF(); //是否使用颜色渐变器 private boolean isGradient = false; //颜色渐变器 private LinearGradient linearGradient; //背景图片和进度条图片 private BitmapDrawable barDrawable,backgroundDrawable; private int barDrawableId = 0,backgroundDrawableId = 0; private boolean isAnimRun = true; //动画模式 private final static int ANIM_NULL = 0; private final static int ANIM_ROTATE = 1; private final static int ANIM_SCALE = 2; private final static int ANIM_ROTATE_SCALE = 3; private final static int ANIM_FRAME = 4; private int animMode = ANIM_NULL; private int rotateRate = 10; private int rotateDegree = 0; private float scaleMax = 1.5f, scaleMin = 0.5f; private float scaleLevel = 1; private float scaleRate = 0.1f; private boolean isScaleIncrease = true; //帧动画图片 private int drawableIds[]; private ArrayList<Drawable> drawableList = new ArrayList<>(); private int frameIndex = 0; private int gradientStartColor = Color.RED, gradientEndColor = Color.YELLOW; public PictureProgressBar(Context context) { super(context); init(); } public PictureProgressBar(Context context, AttributeSet attrs) throws Exception { super(context, attrs); //获取xml属性 TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PictureProgressBar, 0, 0); backGroundColor = typedArray.getColor(R.styleable.PictureProgressBar_backGroundColor, Color.GRAY); barColor = typedArray.getColor(R.styleable.PictureProgressBar_barColor, Color.RED); drawable = typedArray.getDrawable(R.styleable.PictureProgressBar_drawable); halfDrawableWidth = typedArray.getDimensionPixelSize(R.styleable.PictureProgressBar_halfDrawableWidth, 35); halfDrawableHeight = typedArray.getDimensionPixelSize(R.styleable.PictureProgressBar_halfDrawableHeight, 35); drawableHeightOffset = typedArray.getDimensionPixelSize(R.styleable.PictureProgressBar_drawableHeightOffset, 0); isRound = typedArray.getBoolean(R.styleable.PictureProgressBar_isRound, true); roundX = typedArray.getDimensionPixelSize(R.styleable.PictureProgressBar_roundX, 20); roundY = typedArray.getDimensionPixelSize(R.styleable.PictureProgressBar_roundY, 20); progress = typedArray.getInt(R.styleable.PictureProgressBar_progress, 0); max = typedArray.getInt(R.styleable.PictureProgressBar_max, 100); isSetBar = typedArray.getBoolean(R.styleable.PictureProgressBar_isSetBar, false); progressHeight = typedArray.getDimensionPixelSize(R.styleable.PictureProgressBar_progressHeight, 30); progressHeightOffset = typedArray.getDimensionPixelSize(R.styleable.PictureProgressBar_progressHeightOffset, 0); refreshTime = typedArray.getInt(R.styleable.PictureProgressBar_refreshTime, 100); animMode = typedArray.getInt(R.styleable.PictureProgressBar_animMode, ANIM_NULL); rotateRate = typedArray.getInt(R.styleable.PictureProgressBar_rotateRate, 10); rotateDegree = typedArray.getInt(R.styleable.PictureProgressBar_rotateDegree, 0); scaleMax = typedArray.getFloat(R.styleable.PictureProgressBar_scaleMax, 2); scaleMin = typedArray.getFloat(R.styleable.PictureProgressBar_scaleMin, 1); scaleRate = typedArray.getFloat(R.styleable.PictureProgressBar_scaleRate, 0.1f); gradientStartColor = typedArray.getColor(R.styleable.PictureProgressBar_gradientStartColor, Color.RED); gradientEndColor = typedArray.getColor(R.styleable.PictureProgressBar_gradientEndColor, Color.YELLOW); isGradient = typedArray.getBoolean(R.styleable.PictureProgressBar_isGradient, false); backgroundDrawableId = typedArray.getResourceId(R.styleable.PictureProgressBar_backgroundDrawable,0); barDrawableId = typedArray.getResourceId(R.styleable.PictureProgressBar_barDrawable,0); typedArray.recycle(); init(); } public PictureProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } //初始化 private void init() { //初始化画笔 paintBackGround = new Paint(); paintBackGround.setColor(backGroundColor); paintBar = new Paint(); paintBar.setColor(barColor); //在PreDraw时获取View属性,因为在初始化的时候View还没进行Measure getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { getViewTreeObserver().removeOnPreDrawListener(this); if (barDrawableId != 0 && backgroundDrawableId != 0) try { setBarDrawableId(barDrawableId); setBarBackgroundDrawableId(backgroundDrawableId); } catch (Exception e) { e.printStackTrace(); } //是否需要渐变器 if (isGradient) { if (barDrawable == null) { linearGradient = new LinearGradient(0, progressHeight / 2, progressWidth, progressHeight / 2, gradientStartColor, gradientEndColor, Shader.TileMode.CLAMP); paintBar.setShader(linearGradient); } } return false; } }); } @Override protected synchronized void onDraw(Canvas canvas) { // getHandler().removeCallbacksAndMessages(null); //获取进度条当前进度的中心点坐标 x = (int) ((progressWidth - halfDrawableWidth ) * progressPercentage + halfDrawableWidth); y = getHeight() / 2; drawBar(canvas); drawAnimPicture(canvas); //回调Draw过程 postInvalidateDelayed(refreshTime); } //画动画 private void drawAnimPicture(Canvas canvas) { if (isAnimRun) { switch (animMode) { case ANIM_NULL: drawPicture(canvas); break; case ANIM_ROTATE: rotateCanvas(canvas); drawPicture(canvas); break; case ANIM_SCALE: scaleCanvas(canvas); drawPicture(canvas); break; case ANIM_ROTATE_SCALE: rotateCanvas(canvas); scaleCanvas(canvas); drawPicture(canvas); break; case ANIM_FRAME: drawable = drawableList.get(frameIndex); if (drawable == null) { drawable = getResources().getDrawable(drawableIds[frameIndex]); } drawPicture(canvas); if (frameIndex >= drawableIds.length - 1) { frameIndex = 0; } else { frameIndex++; } break; } } else { drawPicture(canvas); } } // 对backgroundDrawable和barDrawable的图片进行缩放以适应进度条的高度,平铺填充 private void updateDrawableBounds(int h) { if (backgroundDrawable != null && barDrawable != null) { int bgWidth; int barWidth; // 根据Drawable资源的宽高计算缩放比例。 int intrinsicWidth = backgroundDrawable.getIntrinsicWidth(); int intrinsicHeight = backgroundDrawable.getIntrinsicHeight(); int barIntrinsicWidth = barDrawable.getIntrinsicWidth(); int barIntrinsicHeight = barDrawable.getIntrinsicHeight(); final float bgIntrinsicAspect = (float) intrinsicWidth / intrinsicHeight; final float barIntrinsicAspect = (float) barIntrinsicWidth/barIntrinsicHeight; bgWidth = (int) (h * bgIntrinsicAspect); barWidth = (int) (h * barIntrinsicAspect); float bgScaleX = (float) bgWidth / intrinsicWidth; float bgScaleY = (float) h / intrinsicHeight; float barScaleX = (float) barWidth / barIntrinsicWidth; float barScaleY = (float) h / barIntrinsicHeight; Matrix bgMatrix = new Matrix(); bgMatrix.postScale(bgScaleX, bgScaleY); BitmapShader bgBitmapShader = new BitmapShader(backgroundDrawable.getBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); bgBitmapShader.setLocalMatrix(bgMatrix); Matrix barMatrix = new Matrix(); barMatrix.postScale(barScaleX, barScaleY); BitmapShader barBitmapShader = new BitmapShader(barDrawable.getBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); barBitmapShader.setLocalMatrix(bgMatrix); // Log.d(TAG, "updateDrawableBoun;ds: width" + bgWidth); // Log.d(TAG, "updateDrawableBounds: height" + bgHeight); paintBackGround.setShader(bgBitmapShader); paintBar.setShader(barBitmapShader); // 设置Drawable的绘制区域。 // barDrawable.setBounds(0, 0, bgWidth, bgHeight); // backgroundDrawable.setBounds(0, 0, bgWidth, bgHeight); } } //画进度条 private void drawBar(Canvas canvas) { if (backgroundDrawable != null && barDrawable != null) { //图片进度条 canvas.save(); canvas.translate(halfDrawableWidth, y - progressHeight / 2 + progressHeightOffset); rectFBG.set(0, 0, progressWidth - halfDrawableWidth , progressHeight); rectFPB.set(0, 0, x - halfDrawableWidth, progressHeight); // rectFBG.set(0, 0, getWidth(), getHeight()); canvas.drawRect(rectFBG, paintBackGround); canvas.drawRect(rectFPB,paintBar); canvas.restore(); } else { //非图片背景处理 rectFBG.set(halfDrawableWidth, y - progressHeight / 2 + progressHeightOffset, progressWidth, y + progressHeight / 2 + progressHeightOffset); rectFPB.set(halfDrawableWidth, y - progressHeight / 2 + progressHeightOffset, x, y + progressHeight / 2 + progressHeightOffset); if (isRound) { canvas.drawRoundRect(rectFBG, roundX, roundY, paintBackGround); if (x > halfDrawableWidth * 2) { canvas.drawRoundRect(rectFPB, roundX, roundY, paintBar); } } else { canvas.drawRect(rectFBG, paintBackGround); canvas.drawRect(rectFPB, paintBar); } } } //旋转画布 private void rotateCanvas(Canvas canvas) { canvas.rotate(rotateDegree % 360, x, y + drawableHeightOffset); rotateDegree += rotateRate; } //伸缩画布 private void scaleCanvas(Canvas canvas) { if (scaleLevel >= scaleMax) { isScaleIncrease = false; } else if (scaleLevel <= scaleMin) { isScaleIncrease = true; } if (isScaleIncrease) { scaleLevel += scaleRate; } else { scaleLevel -= scaleRate; } canvas.scale(scaleLevel, scaleLevel, x, y + drawableHeightOffset); } //画图 private void drawPicture(Canvas canvas) { if (drawable == null && animMode != ANIM_NULL) { Log.e(TAG, "drawable is null"); return; } drawable.setBounds(x - halfDrawableWidth, getHeight() / 2 - halfDrawableHeight + drawableHeightOffset, x + halfDrawableWidth, getHeight() / 2 + halfDrawableHeight + drawableHeightOffset); drawable.draw(canvas); } //重写onMeasure,以自定义获取进度条的宽高 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = MeasureSpec.getSize(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT) { //在这里实现计算需要wrap_content时需要的宽 width = halfDrawableWidth * 2; } if (getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) { //在这里实现计算需要wrap_content时需要的高 height = halfDrawableHeight * 2; } progressWidth = width; //如果不是自定义设置进度条高度,就直接把高度当作进度条高度 if (!isSetBar) { progressHeight = height; } //如果有图片,就为图片预留空间 if (drawable != null || drawableIds != null) { progressWidth = width - halfDrawableWidth; } Log.d(TAG, "onMeasure: progressWidth " + progressWidth); //传入处理后的宽高 setMeasuredDimension(width, height); } //设置进度 public synchronized void setProgress(int progress) { if (progress <= max) { this.progress = progress; } else if (progress < 0) { this.progress = 0; } else { this.progress = max; } progressPercentage = progress / (float) max; doProgressRefresh(); } //进行进度改变之后的操作 private synchronized void doProgressRefresh() { if (onProgressChangeListener != null) { onProgressChangeListener.onOnProgressChange(progress); if (progress >= max) { onProgressChangeListener.onOnProgressFinish(); } } } //设置动画开关 public void setAnimRun(boolean isAnimRun) { this.isAnimRun = isAnimRun; } //设置帧动画时要传入的图片ID数组 public void setDrawableIds(int[] drawableIds) { this.drawableIds = drawableIds; drawableList.clear(); for (int id : drawableIds) { drawableList.add(getResources().getDrawable(id)); } } //设置图片 public void setPicture(int id) { drawable = getResources().getDrawable(id); } //设置颜色渐变器 public void setLinearGradient(LinearGradient linearGradient) { this.linearGradient = linearGradient; } // 设置进度条图片 public void setBarBackgroundDrawableId(int id) throws Exception { Drawable drawable = getResources().getDrawable(id); if (drawable instanceof BitmapDrawable) { backgroundDrawable = (BitmapDrawable) drawable; updateDrawableBounds(progressHeight); }else { throw new Exception("输入的id不是BitmapDrawable的id"); } } // public void setBarBackgroundDrawable(Drawable backgroundDrawable) throws Exception { // if (drawable instanceof BitmapDrawable) { // this.backgroundDrawable = (BitmapDrawable) backgroundDrawable; // updateDrawableBounds(600, progressHeight); // }else { // throw new Exception("输入的id不是BitmapDrawable的id"); // } // } /** * 设置进度条背景图片 * @param id 图片id * @throws Exception 异常 */ public void setBarDrawableId(int id) throws Exception { Drawable drawable = getResources().getDrawable(id); if (drawable instanceof BitmapDrawable) { barDrawable = (BitmapDrawable) drawable; updateDrawableBounds(progressHeight); }else { throw new Exception("输入的id不是BitmapDrawable的id"); } } // public void setBarDrawable(Drawable drawable) throws Exception { //// if (drawable instanceof BitmapDrawable) { // barDrawable = (BitmapDrawable) drawable; // updateDrawableBounds(600, progressHeight); //// }else { //// throw new Exception("输入的id不是BitmapDrawable的id"); //// } // } public LinearGradient getLinearGradient() { return linearGradient; } public int getProgress() { return progress; } public void setMax(int max) { this.max = max; } public int getMax() { return max; } public void setBackGroundColor(int backGroundColor) { this.backGroundColor = backGroundColor; } public int getBackGroundColor() { return backGroundColor; } public void setBarColor(int barColor) { this.barColor = barColor; } public int getBarColor() { return barColor; } public void setDrawable(Drawable drawable) { this.drawable = drawable; } public Drawable getDrawable() { return drawable; } public void setIsRound(boolean isRound) { this.isRound = isRound; } public boolean getIsRound() { return isRound; } public void setProgressHeight(int progressHeight) { this.progressHeight = progressHeight; } public int getProgressHeight() { return progressHeight; } public void setProgressHeightOffset(int progressHeightOffset) { this.progressHeightOffset = progressHeightOffset; } public int getProgressHeightOffset() { return progressHeightOffset; } public void setHalfDrawableWidth(int halfDrawableWidth) { this.halfDrawableWidth = halfDrawableWidth; } public int getHalfDrawableWidth() { return halfDrawableWidth; } public void setDrawableHeightOffset(int drawableHeightOffset) { this.drawableHeightOffset = drawableHeightOffset; } public int getDrawableHeightOffset() { return drawableHeightOffset; } public void setHalfDrawableHeight(int halfDrawableHeight) { this.halfDrawableHeight = halfDrawableHeight; } public int getHalfDrawableHeight() { return halfDrawableHeight; } public void setAnimMode(int animMode) { this.animMode = animMode; } public int getAnimMode() { return animMode; } public void setRotateRate(int rotateRate) { this.rotateRate = rotateRate; } public int getRotateRate() { return rotateRate; } public void setRefreshTime(int refreshTime) { this.refreshTime = refreshTime; } public int getRefreshTime() { return refreshTime; } public void setGradientStartColor(int gradientStartColor) { this.gradientStartColor = gradientStartColor; } public void setGradientEndColor(int gradientEndColor) { this.gradientEndColor = gradientEndColor; } public void setScaleMin(float scaleMin) { this.scaleMin = scaleMin; } public float getScaleMin() { return scaleMin; } public void setScaleMax(float scaleMax) { this.scaleMax = scaleMax; } public float getScaleMax() { return scaleMax; } public void setScaleRate(float scaleRate) { this.scaleRate = scaleRate; } public float getScaleRate() { return scaleRate; } public void setRotateDegree(int rotateDegree) { this.rotateDegree = rotateDegree; } public int getRotateDegree() { return rotateDegree; } public void setRoundX(int roundX) { this.roundX = roundX; } public void setRoundY(int roundY) { this.roundY = roundY; } //设置进度监听器 public void setOnProgressChangeListener(OnProgressChangeListener onProgressChangeListener) { this.onProgressChangeListener = onProgressChangeListener; } //进度监听器 public interface OnProgressChangeListener { //进度改变时的回调 void onOnProgressChange(int progress); //进度完成时的回调 void onOnProgressFinish(); } }