您的位置:首页 > 其它

随记11——我的简单的自定义View之圆形进度条和长形进度条

2017-12-22 11:31 681 查看


女神镇楼

一共两个进度条,一个是水平的进度条,一个是圆形的进度条,效果如下:



先说圆形进度条,继承TextView,有几个自定义属性:

<!--圆形进度条-->
<declare-styleable name="circleProgressView">
<attr name="strokeBgColor" format="color"/>
<attr name="strokeColor" format="color"/>
<attr name="strokeWidth" format="dimension"/>
<attr name="progress" format="integer"/>
<attr name="fromAngle" format="integer"/>
<attr name="isCapRound" format="boolean"/>
</declare-styleable>
strokeBgColor圆环的背景颜色(默认ff0000),strokeColor圆环颜色(默认f6f6f6),strokeWidth圆环宽度(默认10px),progress进度(默认0),fromAngle起始角度(默认0,定义从正上方为0度),isCapRound圆环进度起末是否为圆形(默认为true)。用法如下:

<com.bjl.mypractice.view.CircleProgressView
android:id="@+id/circleProgressView"
android:layout_width="200dp"
android:layout_height="200dp"
app:strokeBgColor="@color/colorPrimary"
app:strokeColor="@color/color_ff0000"
app:strokeWidth="5dp"
app:progress="20"
app:fromAngle="0"
android:textColor="@color/color_ff0000"
android:textSize="16sp"
android:text="张三"
android:gravity="center"/>
View代码如下:

/**
* Created by Administrator on 2017/12/18.
* 圆形进度条
*/

public class CircleProgressView extends android.support.v7.widget.AppCompatTextView {

/**
* 圆环默认宽度
*/
private float defaultStrokeWidth = 10;
/**
* 进度值0~100
*/
private int mProgress;
/**
* 起始角度0~360
* -90为正上方
* 0为3点位置
*/
private int fromAngle = 0;//
//    private int textSize = 14;
//    private int textColor;//默认666666;
//    private String text = "张三";
private boolean isCapRound = true;//进度是开头和结尾否是圆形的
private Paint mPaint;
private Paint mBgPaint;
private Paint mTextPaint;
RectF ovl;//圆环内环绘制的区域
private boolean isProgressing = false;//是否正在绘制进度 防止线程多重绘制

public CircleProgressView(Context context) {
this(context, null);
}

public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

init(attrs);
}

private void init(AttributeSet attrs) {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);

mBgPaint = new Paint();
mBgPaint.setAntiAlias(true);
mBgPaint.setDither(true);
mBgPaint.setStyle(Paint.Style.STROKE);

mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setDither(true);
mTextPaint.setStyle(Paint.Style.FILL);

int strokeColor = Color.parseColor("#ff0000");
int strokeBgColor = Color.parseColor("#f6f6f6");
if (attrs != null){
TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.circleProgressView);
strokeBgColor = array.getColor(R.styleable.circleProgressView_strokeBgColor, Color.parseColor("#f6f6f6"));
strokeColor = array.getColor(R.styleable.circleProgressView_strokeColor, Color.parseColor("#ff0000"));
defaultStrokeWidth = (int) array.getDimension(R.styleable.circleProgressView_strokeWidth, 10);
mProgress = array.getInteger(R.styleable.circleProgressView_progress, 0);
fromAngle = array.getInteger(R.styleable.circleProgressView_fromAngle, 0);
isCapRound = array.getBoolean(R.styleable.circleProgressView_isCapRound, true);
if (fromAngle < 0){
fromAngle = 0;
}else if (fromAngle > 360){
fromAngle = -90 + fromAngle%360;
}
array.recycle();
}
if (isCapRound){
mPaint.setStrokeCap(Paint.Cap.ROUND);
}
mPaint.setStrokeWidth(defaultStrokeWidth);
mPaint.setColor(strokeColor);

mBgPaint.setStrokeWidth(defaultStrokeWidth);
mBgPaint.setColor(strokeBgColor);

}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);

setMeasuredDimension(getDefaultSize(width, widthMeasureSpec), getDefaultSize(height, heightMeasureSpec));

ovl = new RectF(0 + defaultStrokeWidth/2, 0  + defaultStrokeWidth/2, getMeasuredWidth() -  + defaultStrokeWidth/2, getMeasuredHeight() -  + defaultStrokeWidth/2);

}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//        ovl = new RectF(0 + defaultStrokeWidth/2, 0  + defaultStrokeWidth/2, getMeasuredWidth() -  + defaultStrokeWidth/2, getMeasuredHeight() -  + defaultStrokeWidth/2);
canvas.drawArc(ovl, fromAngle - 90, 360, false, mBgPaint);
canvas.drawArc(ovl, fromAngle - 90, 360 * mProgress/100, false, mPaint);
//        canvas.drawText(text, getWidth()/2, getHeight()/2, mTextPaint);

}

public void setProgress(int progress){
if (progress <= 0){
progress = 0;
mProgress  = 0;
postInvalidate();
}else if (progress > 100){
progress = 100;
}

//解决多个线程同时修改界面的问题
if (isProgressing)
isProgressing = false;
final int finalProgress = progress;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
isProgressing = true;
new Thread() {
@Override
public void run() {
super.run();
//防止上一个线程的影响
for (int i = 0; i < finalProgress; i++) {
mProgress = i;
postInvalidate();
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!isProgressing) {
break;
}
}
isProgressing = false;
}
}.start();
}
}, 50);

}

}


下面是长形进度条,同圆形进度条差不多。

自定义属性如下:

<!--长形进度条-->
<declare-styleable name="horProgressView">

<attr name="progressColor" format="color"/>
<attr name="progressBgColor" format="color"/>
<attr name="progress"/>
<attr name="isCapRound"/>

</declare-styleable>
progressColor进度颜色(默认ff0000),progressBgColor进度背景颜色(默认f6f6f6),progress进度(默认0),isCapRound圆角(默认true)

用法同CricleProgressView。代码如下:

/**
* Created by Administrator on 2017/12/19.
* 水平进度条
*/

public class HorProgressView extends View {

private int strokeWidth;//进度条的高度
private Paint mProgressPaint;
private Paint mBgPaint;
private int mProgress;//进度
private int progressColor;//进度颜色 默认ff0000
private int progressBgColor;//进度背景颜色 默认f6f6f6
private boolean isCapRound = true;//进度是开头和结尾否是圆形的
private boolean isProgressing = false;//是否正在绘制进度 防止线程多重绘制

public HorProgressView(Context context) {
this(context, null);
}

public HorProgressView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public HorProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}

private void init(AttributeSet attrs){
mProgressPaint = new Paint();
mProgressPaint.setAntiAlias(true);
mProgressPaint.setDither(false);
//        mProgressPaint.setStyle(Paint.Style.STROKE);
//        mProgressPaint.setStrokeCap(Paint.Cap.ROUND);

//        mBgPaint = new Paint();
//        mBgPaint.setAntiAlias(true);
//        mBgPaint.setDither(false);
////        mBgPaint.setStyle(Paint.Style.STROKE);
//        mBgPaint.setStrokeCap(Paint.Cap.ROUND);

mBgPaint = new Paint();
mBgPaint.setAntiAlias(true);
mBgPaint.setDither(false);
//        mBgPaint.setStyle(Paint.Style.FILL);
//        mBgPaint.setStrokeCap(Paint.Cap.ROUND);

if (attrs != null){
TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.horProgressView);
progressColor = array.getColor(R.styleable.horProgressView_progressColor, Color.parseColor("#ff0000"));
progressBgColor = array.getColor(R.styleable.horProgressView_progressBgColor, Color.parseColor("#f6f6f6"));
mProgress = array.getInteger(R.styleable.horProgressView_progress, 0);
isCapRound = array.getBoolean(R.styleable.horProgressView_isCapRound, true);
if (mProgress < 0){
mProgress = 0;
}else if (mProgress > 100){
mProgress = 100;
}
array.recycle();
}
if (isCapRound){
mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
mBgPaint.setStrokeCap(Paint.Cap.ROUND);
}
mProgressPaint.setColor(progressColor);
mBgPaint.setColor(progressBgColor);

}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
//        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//        if (heightMode == MeasureSpec.EXACTLY)
setMeasuredDimension(getDefaultSize(width, widthMeasureSpec), getDefaultSize(height, heightMeasureSpec));

strokeWidth = getMeasuredHeight();
mProgressPaint.setStrokeWidth(getMeasuredHeight());
mBgPaint.setStrokeWidth(getMeasuredHeight());
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

if (isCapRound){
//有圆角
canvas.drawLine(getHeight()/2, getHeight()/2, getWidth() - getHeight()/2, getHeight()/2, mBgPaint);
//        canvas.drawRect(0, 0, getWidth(), getHeight(),mBgPaint);
canvas.drawLine(getHeight()/2, getHeight()/2, (getWidth() - getHeight()) * mProgress / 100 + getHeight()/2, getHeight()/2, mProgressPaint);
}else {
canvas.drawLine(0, getHeight()/2, getWidth(), getHeight()/2, mBgPaint);
canvas.drawLine(0, getHeight()/2, getWidth() * mProgress / 100 , getHeight()/2, mProgressPaint);
}

}

public void setProgress(int progress) {
if (progress <= 0){
progress = 0;
mProgress  = 0;
postInvalidate();
}else if (progress > 100){
progress = 100;
}

//解决多个线程同时修改界面的问题
if (isProgressing)
isProgressing = false;
final int finalProgress = progress;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
isProgressing = true;
new Thread() {
@Override
public void run() {
super.run();
//防止上一个线程的影响
for (int i = 0; i < finalProgress; i++) {
mProgress = i;
postInvalidate();
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!isProgressing) {
break;
}
}
isProgressing = false;
}
}.start();
}
}, 50);
}
}
下一篇是自定义SeekBar,还有一个我个人比较满意的ColorLoadingView。
本期代码下载地址:回来跟下面的SeekBar及ColorLoadingView一起发吧。

Demo下载链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐