1 前言
自定义view是android的一个难点,逃避了那么久, 现在觉得不会的东西还是得要从基础补起来,自定义进度条网上也一大堆,这篇文章只是一个入门的学习笔记,高手请略过...
2 view的工作流程
这里只说自定义环形进度条,比较入门级,所以只做简单介绍,显得简洁,看着舒服,后续会讲详细的流程方法,所以先来看看view的大体工作流程。
a) measure 确实view的测量宽/高 (测三围,看五官)
b) layout 确定view的四个顶点的位置 (站在舞台位置)
c} ondraw 将view绘制到屏幕上 (打扮好出场)
3 工作图
4 流程步骤
- 自定义view的相关属性
// 圆环的颜色
private int ringColor = 0xFF00FF00;
// 圆环进度的颜色
private int ringProgressColor = 0xFFFF0000;
//圆环的宽度
private int ringWidth = 10;
// 字体大小
private int textSize = 20;
// 字体颜色
private int textColor = 0xFF0000FF;
// 当前进度
private int currentProgress = 60;
// 最大进度
private int maxProgress = 100;
// 得到控件的宽度
private int width;
// 画笔对象
private Paint paint;
- 在values下新建attr.xml
<!-- 自定义环形进度条的属性-->
<declare-styleable name="RingProgressView">
<attr name="ringColor" format="color"/>
<attr name="ringProgressColor" format="color"/>
<attr name="ringWidth" format="dimension"/>
<attr name="textSize" format="dimension"/>
<attr name="textColor" format="color"/>
<attr name="currentProgress" format="integer"/>
<attr name="maxProgress" format="integer"/>
</declare-styleable>
- 通过TypedArray获取自定义view的相关属性
public RingProgressView(Context context) {
this(context, null);
}
public RingProgressView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RingProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
// 得到自定义资源数组
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RingProgressView);
ringColor = typedArray.getColor(R.styleable.RingProgressView_ringColor, ringColor);
ringProgressColor = typedArray.getColor(R.styleable.RingProgressView_ringProgressColor, ringProgressColor);
ringWidth = (int) typedArray.getDimension(R.styleable.RingProgressView_ringWidth, dip2px(10));
textSize = (int) typedArray.getDimension(R.styleable.RingProgressView_textSize, dip2px(20));
textColor = typedArray.getColor(R.styleable.RingProgressView_textColor, textColor);
currentProgress = typedArray.getInt(R.styleable.RingProgressView_currentProgress, currentProgress);
maxProgress = typedArray.getColor(R.styleable.RingProgressView_maxProgress, maxProgress);
typedArray.recycle();
paint = new Paint();
// 抗锯齿
paint.setAntiAlias(true);
}
- 画同心圆
// 1. 计算圆心坐标及半径
float centerX = width / 2;
float centerY = width / 2;
float radius = width / 2 - ringWidth / 2;
// 2. 画圆环
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(ringWidth);
paint.setColor(ringColor);
canvas.drawCircle(centerX, centerY, radius, paint);
- 画圆弧进度
// 3. 画圆弧
RectF rectF = new RectF(ringWidth / 2, ringWidth / 2, width - ringWidth / 2, width - ringWidth / 2);
paint.setColor(ringProgressColor);
canvas.drawArc(rectF, 0, currentProgress * 360 / maxProgress, false, paint);
- 画百分比文本框
// 3. 画文本
String text = currentProgress * 100 / maxProgress + "%";
paint.setColor(textColor);
paint.setTextSize(textSize);
// 要重新设置宽度为0
paint.setStrokeWidth(0);
// 得到指定文本边界的指定大小
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
// float textWidth = paint.measureText(text);
// float textHigh = textSize;
canvas.drawText(text, width / 2 - bounds.width() / 2, width / 2 + bounds.height() / 2, paint);
学习心得
- 自定义属性
1.通过新建attrs.xml,增加declare-styleable标签来定义相关的属性
2.通过TypedArray获取自定义的资源数组
- getDimension、getDimensionPixelOffset、getDimensionPixelSize区别
getDimension和getDimensionPixelOffset的功能都是获取某个dimen的值,但是如果单位是dp或sp,则需要将其乘以density。如果是px,则不乘。并且getDimension返回float,getDimensionPixelOffset返回int.
而getDimensionPixelSize则不管写的是dp,sp,px, 都会乘以denstiy.
- Paint类measureText与getTextBounds的区别
在使用Canvas绘制文字时,需要得到字符串的长度,Paint类内给了两个方法,measureText(),getTextBounds(),但是实际的宽度meauserText()要比getTextBounds()大一点,但是相差不会太大
- Paint画圆的半径之谜
为什么圆的半径是radius = width / 2 - ringWidth / 2而不是width / 2 或者width / 2 - ringWidth?
其实我们画的是圆环,有宽度的,Paint画刷其实是从圆环的中心点绘制的,所以半径是 width / 2 - ringWidth / 2,如果你不信,看下图:
自定义环形进度条到此结束,感谢你的浏览
完整版代码:戳这里