自定义控件的几个步骤:
1.在attrs.xml文件声明自定义属性。
2.在此类中通过TypedArray拿到自定义属性的值。
3.根据这些值完成onMeasure,onLayout()和onDraw()函数。
>
attrs.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="progress_reach" format="color"></attr>
<attr name="progress_unreach" format="color"></attr>
<attr name="progress_reach_height" format="dimension"></attr>
<attr name="progress_unreach_height" format="dimension"></attr>
<attr name="progress_text_color" format="color"></attr>
<attr name="progress_text_size" format="dimension"></attr>
<attr name="progress_text_offset" format="dimension"></attr>
<attr name="progress_radius" format="dimension"></attr>
<declare-styleable name="MyProgressBar">
<attr name="progress_reach"></attr>
<attr name="progress_unreach"></attr>
<attr name="progress_reach_height"></attr>
<attr name="progress_unreach_height"></attr>
<attr name="progress_text_color" ></attr>
<attr name="progress_text_size"></attr>
<attr name="progress_text_offset"></attr>
</declare-styleable>
<declare-styleable name="MyRoundProgressBar">
<attr name="progress_radius"></attr>
<!--这里是私有属性-->
</declare-styleable>
</resources>
直线进度条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是包名)
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ProgressActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<view.MyProgressBar
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:id="@+id/myprogress_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="0"
android:padding="5dp"
app:progress_reach="@color/Green"
app:progress_unreach="@color/c3"
app:progress_text_color="@color/Green"
app:progress_text_size="16sp"
android:layout_marginTop="30dp"/>
<view.MyRoundProgressBar
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:id="@+id/myprogress_three"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="0"
android:padding="5dp"
app:progress_radius="80dp"
android:layout_marginTop="30dp"
app:progress_text_size="20sp"
app:progress_text_color="@color/colorPrimaryDark"
app:progress_reach="@color/colorPrimaryDark"
app:progress_unreach="@color/c8"
/>
<view.MyProgressBar
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:id="@+id/myprogress_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="100"
android:padding="5dp"
app:progress_reach="@color/c1"
app:progress_unreach="@color/WeChat"
app:progress_text_color="@color/c1"
app:progress_text_size="16sp"
android:layout_marginTop="30dp"/>
<view.MyRoundProgressBar
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:id="@+id/myprogress_four"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="100"
android:padding="5dp"
app:progress_radius="60dp"
android:layout_marginTop="30dp"
app:progress_text_size="16sp"
app:progress_text_color="@color/c7"
app:progress_reach="@color/c7"
app:progress_unreach="@color/WeChat"
/>
</LinearLayout>
</ScrollView>
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);
}
}
演示效果图