自定义控件的几个步骤:
1.在attrs.xml文件声明自定义属性。
2.在此类中通过TypedArray拿到自定义属性的值。
3.根据这些值完成onMeasure,onLayout()和onDraw()函数。
>
attrs.xml文件
直线进度条MyProgressBar
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ProgressBar;
import com.example.yang.crazydemo.R;
/**
* createtime:2019/8/12
* author:Yang
* describe:
*/
public class MyProgressBar extends ProgressBar {
private static final int DEFAULT_TEXT_SIZE=10;//sp
private static final int DEFAULT_TEXT_COLOR=0xFFFC00D1;
private static final int DEFAULT_COLOR_UNREACH=0XFFD3D6DA;
private static final int DEFAULT_COLOR_REACH=DEFAULT_TEXT_COLOR;
private static final int DEFAULT_HEIGHT_REACH=2;//dp
private static final int DEFAULT_HEIGHT_UNREACH=2;//dp
private static final int DEFAULT_TEXT_OFFSET=10;//dp
protected int mTextColor=DEFAULT_TEXT_COLOR;
protected int mTextSize=Sptopx(DEFAULT_TEXT_SIZE);
protected int mTextOffset=Dptopx(DEFAULT_TEXT_OFFSET);
protected int mReachColor=DEFAULT_COLOR_REACH;
protected int mUnReachColor=DEFAULT_COLOR_UNREACH;
protected int mReachHeight=Dptopx(DEFAULT_HEIGHT_REACH);
protected int mUnReachHeight=Dptopx(DEFAULT_HEIGHT_UNREACH);
protected Paint mpaint=new Paint();
protected int mRealWidth;
public MyProgressBar(Context context) {
this(context,null);
}
public MyProgressBar(Context context,AttributeSet attrs) {
this(context,attrs,0);
}
public MyProgressBar(Context context,AttributeSet attrs,int defStyle) {
super(context,attrs,defStyle);
ObtainStyleAttrs(attrs);
}
protected void ObtainStyleAttrs(AttributeSet attrs) {
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MyProgressBar);
mTextSize=(int) typedArray.getDimension(R.styleable.MyProgressBar_progress_text_size, mTextSize);
mReachColor=typedArray.getColor(R.styleable.MyProgressBar_progress_reach, mReachColor);
mUnReachColor=typedArray.getColor(R.styleable.MyProgressBar_progress_unreach,mUnReachColor);
mTextColor=typedArray.getColor(R.styleable.MyProgressBar_progress_text_color,mTextColor );
mTextOffset= (int) typedArray.getDimension(R.styleable.MyProgressBar_progress_text_offset,mTextOffset);
mUnReachHeight= (int) typedArray.getDimension(R.styleable.MyProgressBar_progress_unreach_height,mUnReachHeight);
mReachHeight= (int) typedArray.getDimension(R.styleable.MyProgressBar_progress_reach_height,mReachHeight);
typedArray.recycle();
mpaint.setTextSize(mTextSize);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthVal=MeasureSpec.getSize(widthMeasureSpec);
int height=MeasureHeight(heightMeasureSpec);
setMeasuredDimension(widthVal, height);
mRealWidth=getMeasuredWidth()-getPaddingLeft()-getPaddingRight();
}
@Override
protected synchronized void onDraw(Canvas canvas) {
canvas.save();
canvas.translate(getPaddingLeft(), getHeight()/2);
boolean NOneedUnreach=false;
float radio=getProgress()*1.0f/getMax();
String text=getProgress()+"%";
float textWidth=mpaint.measureText(text);
float ProgressX=radio*mRealWidth;
if(ProgressX+textWidth>mRealWidth){
ProgressX=mRealWidth-textWidth;
NOneedUnreach=true;
}
float EndX=ProgressX-mTextOffset/2;
//绘制reach
if(EndX>0){
mpaint.setColor(mReachColor);
mpaint.setStrokeWidth(mReachHeight);
canvas.drawLine(0, 0, EndX, 0, mpaint);
}
//绘制text
mpaint.setColor(mTextColor);
int y= (int) (-(mpaint.ascent()+mpaint.descent())/2);
canvas.drawText(text, ProgressX, y,mpaint);
//绘制Unreach
if(!NOneedUnreach){
mpaint.setColor(mUnReachColor);
float start=ProgressX+mTextOffset/2+textWidth;
mpaint.setStrokeWidth(mUnReachHeight);
canvas.drawLine(start, 0,mRealWidth, 0, mpaint);
}
canvas.restore();
}
private int MeasureHeight(int heightMeasureSpec) {
int result=0;
int Mode=MeasureSpec.getMode(heightMeasureSpec);
int Size=MeasureSpec.getSize(heightMeasureSpec);
if(Mode==MeasureSpec.EXACTLY){
result=Size;
}else{
int TextSize= (int) (mpaint.descent()-mpaint.ascent());
result=getPaddingTop()+getPaddingBottom()+Math.max(Math.max(mReachHeight, mUnReachHeight)
, Math.abs(TextSize));
if(Mode==MeasureSpec.AT_MOST){
result=Math.min(result, Size);
}
}
return result;
}
public int Dptopx(int dpval){
return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpval, getResources().getDisplayMetrics());
}
public int Sptopx(int spval){
return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spval,
getResources().getDisplayMetrics());
}
}
圆形进度条MyRoundProgressBar
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import com.example.yang.crazydemo.R;
/**
* createtime:2019/8/13
* author:Yang
* describe:圆形的进度条
*/
public class MyRoundProgressBar extends MyProgressBar {
private int mRadius=Dptopx(30);
private int mMaxPaintWidth;
public MyRoundProgressBar(Context context) {
this(context,null);
}
public MyRoundProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyRoundProgressBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mReachHeight= (int) (2.5f*mUnReachHeight);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyRoundProgressBar);
mRadius= (int) typedArray.getDimension(R.styleable.MyRoundProgressBar_progress_radius, mRadius);
typedArray.recycle();
mpaint.setAntiAlias(true);
mpaint.setDither(true);
mpaint.setStyle(Paint.Style.STROKE);
mpaint.setStrokeCap(Paint.Cap.ROUND);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mMaxPaintWidth=Math.max(mReachHeight, mUnReachHeight);
int expect=2*mRadius+mMaxPaintWidth+getPaddingLeft()+getPaddingRight();
int height=resolveSize(expect, heightMeasureSpec);
int width=resolveSize(expect,widthMeasureSpec);
int realWidth=Math.min(height, width);
mRadius=(realWidth-getPaddingRight()-getPaddingLeft()-mMaxPaintWidth)/2;
setMeasuredDimension(realWidth, realWidth);
}
@Override
protected synchronized void onDraw(Canvas canvas) {
String text=getProgress()+"%";
int textwidth= (int) mpaint.measureText(text);
int textheight=(int)(mpaint.descent()+mpaint.ascent())/2;
canvas.save();
canvas.translate(getPaddingLeft()+mMaxPaintWidth/2, getPaddingTop()+mMaxPaintWidth/2);
mpaint.setStyle(Paint.Style.STROKE);
//绘制unReachbar
mpaint.setColor(mUnReachColor);
mpaint.setStrokeWidth(mUnReachHeight);
canvas.drawCircle(mRadius, mRadius,mRadius , mpaint);
//绘制Reachbar
mpaint.setColor(mReachColor);
mpaint.setStrokeWidth(mReachHeight);
float sweepAngle=getProgress()*1.0f/getMax()*360;
canvas.drawArc(new RectF(0,0,2*mRadius,2*mRadius)
, 0, sweepAngle, false,mpaint );
//绘制Text
mpaint.setStyle(Paint.Style.FILL);
mpaint.setColor(mTextColor);
canvas.drawText(text, mRadius-textwidth/2, mRadius-textheight, mpaint);
canvas.restore();
}
}
布局代码(view是包名)
Activity使用代码
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import view.MyProgressBar;
import view.MyRoundProgressBar;
public class ProgressActivity extends AppCompatActivity {
private MyProgressBar progressBarone;
private MyRoundProgressBar myRoundProgressBar;
private MyProgressBar progressBartwo;
private MyRoundProgressBar myRoundProgressBartwo;
private static final int UPDATA_MSG=0x111;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
int ProgressX=progressBarone.getProgress();
int ProgressY=progressBartwo.getProgress();
progressBarone.setProgress(++ProgressX);
myRoundProgressBar.setProgress(++ProgressX);
progressBartwo.setProgress(--ProgressY);
myRoundProgressBartwo.setProgress(--ProgressY);
while(progressBarone.getProgress()>100){
removeMessages(UPDATA_MSG);
}
while (progressBartwo.getProgress()<0){
removeMessages(UPDATA_MSG);
}
handler.sendEmptyMessageDelayed(UPDATA_MSG, 100);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_progress);
progressBarone=findViewById(R.id.myprogress_one);
myRoundProgressBar=findViewById(R.id.myprogress_three);
progressBartwo=findViewById(R.id.myprogress_two);
myRoundProgressBartwo=findViewById(R.id.myprogress_four);
Message msg=new Message();
msg.what=1;
handler.sendMessage(msg);
}
}
演示效果图