CircleProgressBar
来做个自定义控件CircleProgressBar
这个之前在GitHub上面看到过,而且有很多样式
我们也来试着做一下
步骤
先来个类,当然要实现3个构造方法
public class CircleProgressBar extends View{
public CircleProgressBar(Context context) {
super(context);
}
public CircleProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
第一个,是在代码中new出来的时候调用的
第二个,布局在xml中,系统去调用的
第三个,一般就是第二个去调用,第三个参数是自定义属性
所以第二个可以改成
public CircleProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
第一个也可以改成
public CircleProgressBar(Context context) {
this(context, null);
}
接下来我们要搞一些针对这个CircleProgressBar的自定义属性
创建一个attrs.xml在values中
然后我们增加属性
<resources>
<declare-styleable name="CircleProgressBar">
<!-- 外层圆的颜色-->
<attr name="roundColor" format="color"/>
<!-- 弧形进度的颜色-->
<attr name="roundProgressColor" format="color"/>
<!-- 圆环的宽度-->
<attr name="roundWidth" format="dimension"></attr>
<!-- 中间百分比文字的颜色-->
<attr name="textColor" format="color"/>
<!-- 中间百分比文字的大小-->
<attr name="textSize" format="dimension"/>
</declare-styleable>
</resources>
接下来进行初始化
我们在构造函数中初始化一下
拿到TypedArray,再获取自定义属性
public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar, defStyleAttr, 0);
mRoundColor = typedArray.getColor(R.styleable.CircleProgressBar_roundColor, Color.RED);
mRoundProgressColor = typedArray.getColor(R.styleable.CircleProgressBar_roundProgressColor, Color.GREEN);
mRoundWidth = typedArray.getDimension(R.styleable.CircleProgressBar_roundWidth, UiUtil.getInstance().dpToPx(8));
mTextColor = typedArray.getColor(R.styleable.CircleProgressBar_textColor, Color.BLACK);
mTextSize = typedArray.getDimension(R.styleable.CircleProgressBar_textSize, UiUtil.getInstance().dpToPx(20));
}
然后我们绘制一下
覆写onDraw方法,还要在构造方法中初始化画笔
mPaint = new Paint();
mPaint.setAntiAlias(true);
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
接着开始绘制
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//控件宽度
int width = getWidth();
//圆心和半径
float center = width * 0.5f;
float radius = center - mRoundWidth;
//圆心坐标
float cx=center;
float cy=center;
//画笔属性
mPaint.setColor(mRoundColor);
mPaint.setStrokeWidth(mRoundWidth);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(cx,cy,radius,mPaint);
}
然后是画这个圆的进度
我们根据参数先创建出来
float oval;
float startAngle;
float sweepAngle;
canvas.drawArc(oval,startAngle,sweepAngle,true,mPaint);
这些都是什么意思呢
1.控制圆的矩形
2.开始角度
3.扫过的角度
RectF oval = new RectF(mRoundWidth,mRoundWidth,width-mRoundWidth,width-mRoundWidth);
float startAngle=0;
float sweepAngle=225;
mPaint.setColor(mRoundProgressColor);
canvas.drawArc(oval,startAngle,sweepAngle,false,mPaint);
然后绘制文字
//绘制文字
String text = sweepAngle / 360 + "%";
Rect bounds = new Rect();
mPaint.getTextBounds(text, 0, text.length(), bounds);
int textHeight = bounds.height();
int textWidth = bounds.width();
float x = center - textWidth*0.5f;
float y = center - textHeight*0.5f;
mPaint.setColor(mTextColor);
mPaint.setTextSize(mTextSize);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawText(text, x, y, mPaint);
我们来设置动态修改进度
//定义一个targetProgress保存目标进度
private int targerProgress;
public void setRoundProgressWithAnimation(int roundProgress) {
targerProgress=roundProgress;
mHandler.sendEmptyMessage(0);
}
//创建handler来动态修改
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (mRoundProgress < targerProgress) {
mRoundProgress++;
invalidate();
sendEmptyMessageDelayed(0, 25);
}
}
};
最后优化一下
来个方法释放handler
public void release() {
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
}
}
在Fragment的onDestroy方法里调用
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
if (mCpbHomeCircle != null) {
mCpbHomeCircle.release();
}
}