女神鎮樓
一共兩個進度條,一個是水準的進度條,一個是圓形的進度條,效果如下:
先說圓形進度條,繼承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下載下傳連結