下载进度条控件
package com.zhuoyi.common.widgets;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Paint.Join;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.zhuoyi.market.R;
/**
- Created by wubo on 2017/11/27.
*/
public class DownLoadProgressButton extends TextView {
private static final String TAG = "DownLoadProgressButton";
private final String FREE_STATE_STR ="下载";
private final String DOWNLOADING_STATE_STR ="暂停";
private final String PAUSE_STATE_STR ="继续";
private final String DOWNLOAD_COMPLETE_STR ="安装";
private final String DOWNLOAD_COMPLETE_OPEN_STR ="打开";
public static final int DOWNLOAD_FREE_STATE =0;
public static final int DOWNLOADING_STATE=1;
public static final int DOWNLOAD_PAUSE_STATE =2;
public static final int DOWNLOAD_COMPLETE_STATE =3;
public static final int DOWNLOAD_COMPLETE_OPEN_STATE =4;
private RectF mDrawBgRectF;
private Canvas mProgressCanvas;
private Bitmap mProgressBitmap;
private int mDownLoadState;
/**
* textSize类型是sp还是px
*/
public enum TextSizeType{
SP,PX
}
private final int DEFAULT_TEXT_SIZE=14;
private int mMeasureWidth;
private int mMeasureHeight;
private float mTextSize;
private String mStateTextCurrent="";
private Context mContext;
private int mDefaultWidth;
private int mDefaultHeight;
private Paint mPaint=new Paint();
private Rect mTextBounds = new Rect();
private Path mPath=new Path();
private int mProgressColor;
private int mTextColor;
private float mProgressCurrent;
private float mProgressMax;
private int mCornerRadius;
private int mBorderWidth;
public DownLoadProgressButton(Context context) {
this(context,null);
}
public DownLoadProgressButton(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public DownLoadProgressButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initParams();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DownLoadProgressButton);
for (int i = 0; i < a.getIndexCount(); i++) {
switch (a.getIndex(i)) {
case R.styleable.DownLoadProgressButton_progress_color:
mProgressColor = a.getColor(R.styleable.DownLoadProgressButton_progress_color, Color.parseColor("#22b65d"));
break;
case R.styleable.DownLoadProgressButton_text_color:
mTextColor= a.getColor(R.styleable.DownLoadProgressButton_text_color, Color.parseColor("#22b65d"));
break;
case R.styleable.DownLoadProgressButton_corner_radius:
mCornerRadius=a.getDimensionPixelOffset(R.styleable.DownLoadProgressButton_corner_radius,0);
break;
case R.styleable.DownLoadProgressButton_text:
mStateTextCurrent=a.getString(R.styleable.DownLoadProgressButton_text);
break;
case R.styleable.DownLoadProgressButton_progress:
mProgressCurrent=a.getFloat(R.styleable.DownLoadProgressButton_progress,0);
break;
case R.styleable.DownLoadProgressButton_max_progress:
mProgressMax=a.getFloat(R.styleable.DownLoadProgressButton_max_progress,100);
break;
}
}
a.recycle();
}
private void initParams() {
mTextSize =sp2Px(DEFAULT_TEXT_SIZE);
mBorderWidth=dp2Px(1f);
// mStateTextCurrent= FREE_STATE_STR;
mCornerRadius= dp2Px(10);
// mProgressColor= Color.parseColor("#f87908");
mTextColor=mProgressColor;
initDefaultMeasureWidth();
initPaint();
mProgressMax=100;
}
private void initPaint() {
mPaint.setAntiAlias(true);
mPaint.setStrokeJoin(Join.ROUND);
}
private void initDefaultMeasureWidth() {
mTextBounds.setEmpty();
mPaint.setTextSize(mTextSize);
mPaint.getTextBounds(mStateTextCurrent,0, mStateTextCurrent.length(),mTextBounds);
int textWidth = mTextBounds.width();
int textHeight = mTextBounds.height();
// 设置默认控件大小,默认宽高为字体宽高二倍
mDefaultWidth= (int) (textWidth*1.5f);
mDefaultHeight=textHeight*2;
}
private float sp2Px(float sp){
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, mContext.getResources().getDisplayMetrics());
}
private int dp2Px(float dp){
return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, dp, mContext.getResources().getDisplayMetrics())+0.5f);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize= MeasureSpec.getSize(widthMeasureSpec);
int widthMode= MeasureSpec.getMode(widthMeasureSpec);
int heightSize= MeasureSpec.getSize(heightMeasureSpec);
int heightMode= MeasureSpec.getMode(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
mMeasureWidth = widthSize;
} else {
if(widthSize!=0){
mMeasureWidth = Math.min(mDefaultWidth, widthSize);
}else{
mMeasureWidth=mDefaultWidth;
}
}
if (heightMode == MeasureSpec.EXACTLY) {
mMeasureHeight = heightSize;
} else {
if(heightSize!=0){
mMeasureHeight = Math.min(mDefaultHeight, heightSize);
}else{
mMeasureHeight=mDefaultHeight;
}
}
mDrawBgRectF = new RectF(mBorderWidth, mBorderWidth, mMeasureWidth - mBorderWidth, mMeasureHeight - mBorderWidth);
if(mMeasureWidth>0&&mMeasureHeight>0){
mProgressBitmap = Bitmap.createBitmap(mMeasureWidth - mBorderWidth, mMeasureHeight - mBorderWidth, Config.ARGB_4444);
mProgressCanvas = new Canvas(mProgressBitmap);
}
setMeasuredDimension(mMeasureWidth,mMeasureHeight);
}
@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
drawBorder(canvas);
if(null!=mProgressBitmap){
drawProgress(canvas);
}
drawText(canvas);
drawProgressShadeText(canvas);
}
private void drawProgressShadeText(Canvas canvas) {
mPaint.setColor(Color.WHITE);
FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt();
int tWidth =mTextBounds.width();
float xCoordinate = (mMeasureWidth - tWidth) / 2;
float baseline = (mMeasureHeight -fontMetricsInt.bottom+fontMetricsInt.top) / 2-fontMetricsInt.top;
float progressWidth = (mProgressCurrent / mProgressMax) *mMeasureWidth;
if(progressWidth > xCoordinate){
canvas.save(Canvas.CLIP_SAVE_FLAG);
float right = Math.min(progressWidth, xCoordinate + tWidth * 1.1f);
canvas.clipRect(xCoordinate, 0, right, mMeasureHeight);
canvas.drawText(mStateTextCurrent, xCoordinate, baseline, mPaint);
canvas.restore();
}
}
private void drawText(Canvas canvas) {
mTextBounds.setEmpty();
mPaint.setColor(mTextColor);
mPaint.getTextBounds(mStateTextCurrent, 0, mStateTextCurrent.length(), mTextBounds);
FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt();
int tWidth =mTextBounds.width();
float xCoordinate = (mMeasureWidth - tWidth) / 2;
float baseline = (mMeasureHeight -fontMetricsInt.bottom+fontMetricsInt.top) / 2-fontMetricsInt.top;
canvas.drawText(mStateTextCurrent, xCoordinate, baseline, mPaint);
}
private void drawProgress(Canvas canvas) {
mPaint.setStyle(Paint.Style.FILL);
//mPaint.setStrokeWidth(0);
mPaint.setColor(mProgressColor);
mProgressCanvas.save(Canvas.CLIP_SAVE_FLAG);
float right = (mProgressCurrent / mProgressMax) * mMeasureWidth;
mProgressCanvas.clipRect(0, 0, right, mMeasureHeight);
mProgressCanvas.drawColor(mProgressColor );
mProgressCanvas.restore();
mPaint.setShader(new BitmapShader(mProgressBitmap, TileMode.CLAMP, TileMode.CLAMP));
canvas.drawRoundRect(mDrawBgRectF,mCornerRadius, mCornerRadius, mPaint);
mPaint.setShader(null);
}
private void drawBorder(Canvas canvas) {
mPaint.setStyle(Style.STROKE);
mPaint.setColor(mProgressColor);
mPaint.setStrokeWidth(dp2Px(0.5f));
// mPath.moveTo(mCornerRadius,0);
/* mPath.moveTo(mCornerRadius,0);
mPath.lineTo(mMeasureWidth-mCornerRadius,0);
mPath.moveTo(mMeasureWidth-mCornerRadius,0);
mPath.quadTo(mMeasureWidth,0,mMeasureWidth,mCornerRadius);
mPath.moveTo(mMeasureWidth,mCornerRadius);
mPath.lineTo(mMeasureWidth,mMeasureHeight-mCornerRadius);
mPath.moveTo(mMeasureWidth,mMeasureHeight-mCornerRadius);
mPath.quadTo(mMeasureWidth,mMeasureHeight,mMeasureWidth-mCornerRadius,mMeasureHeight);
mPath.moveTo(mMeasureWidth-mCornerRadius,mMeasureHeight);
mPath.lineTo(mCornerRadius,mMeasureHeight);
mPath.moveTo(mCornerRadius,mMeasureHeight);
mPath.quadTo(0,mMeasureHeight,0,mMeasureHeight-mCornerRadius);
mPath.moveTo(0,mMeasureHeight-mCornerRadius);
mPath.lineTo(0,mCornerRadius);
mPath.moveTo(0,mCornerRadius);
mPath.quadTo(0,0,mCornerRadius,0);
*/
canvas.drawRoundRect(mDrawBgRectF,mCornerRadius,mCornerRadius, mPaint);
}
public void setProgress(float progress){
if(progress>=mProgressMax){
mProgressCurrent=mProgressMax;
}else{
mProgressCurrent=progress;
}
invalidate();
}
public void setMaxProgress(float progressMax){
mProgressMax=progressMax;
}
public void setState(int downLoadState){
mDownLoadState = downLoadState;
Log.e(TAG,"downLoadState: "+downLoadState);
switch (downLoadState){
case DOWNLOAD_FREE_STATE:
mStateTextCurrent=FREE_STATE_STR;
break;
case DOWNLOADING_STATE:
mStateTextCurrent=DOWNLOADING_STATE_STR;
break;
case DOWNLOAD_PAUSE_STATE:
mStateTextCurrent=PAUSE_STATE_STR;
break;
case DOWNLOAD_COMPLETE_OPEN_STATE:
mStateTextCurrent=DOWNLOAD_COMPLETE_OPEN_STR;
break;
case DOWNLOAD_COMPLETE_STATE:
mStateTextCurrent=DOWNLOAD_COMPLETE_STR;
break;
}
invalidate();
}
public void setTextSize(int textSize,TextSizeType sizeType){
if(sizeType== TextSizeType.SP){
mTextSize =sp2Px(textSize);
}else if(sizeType== TextSizeType.PX){
mTextSize=textSize;
}
initDefaultMeasureWidth();
requestLayout();
}
public int getDownLoadState(){
return mDownLoadState;
}
public void setProgressColor(int color){
mProgressColor=color;
invalidate();
}
/**
* set text
* */
public void setButtonText(String text){
mStateTextCurrent=text;
initDefaultMeasureWidth();
requestLayout();
}
public void setCornerRadius(int radius){
mCornerRadius=radius;
invalidate();
}
public void setTextColor(int textColor){
mTextColor=textColor;
invalidate();
}
}