随记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下载链接
相关文章推荐
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 自定义带数字的圆形进度条和中间是文字的圆形进度条View
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)