通过这个view大致了解了几个方法,可通过PathEffect给path设置样式;
大致分三步:
第一步:通过canvas.drawArc()方法先把圆弧画出来
第二步:画刻度(这里通过给画笔设置PathEffect的方法实现刻度绘制,并非for循环画线)
第三步:画指针(这里需要了解正弦余弦,其实都是API的方法,直接调用即可,但需要自己理解)
public class DashboardView extends View {
// 画笔
Paint mPaint;
// 画刻度使用
Path dashPath;
// path效果 比DashPathEffect 多一个前缀Path ,可理解为使用一个Path 来绘制
PathDashPathEffect effect;
// 圆弧半径
private float mRadius = UnitUtil.dp2px(120);
// 未封口的角度
private int remainAngle = 100;
// 指针长度
private float pointerLength = UnitUtil.dp2px(90);
// 刻度数量
private int scaleCount = 16;
// 指针指向的刻度
private int mAngle = 10;
public DashboardView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
// 此模块代码会给随构造函数super()后执行
{
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#228fba"));
// 2dp,在view中进行绘制时直接使用2是像素,所以需要用工具类将2dp转为对应的像素值
mPaint.setStrokeWidth(UnitUtil.dp2px(2));
mPaint.setStyle(Paint.Style.STROKE);
/*--------------------------下面内容第二步画刻度时使用-------------------------------*/
// 刻度使用path,这个算是一个小刻度 给PathDashPathEffect使用
dashPath = new Path();
dashPath.addRect(
0, 0,
UnitUtil.dp2px(2), UnitUtil.dp2px(8),
Path.Direction.CW // CW 顺时针 CCW逆时针
);
// 创建弧度的path,然后使用PathMeasure测量这个圆弧的长度
Path arcPath = new Path();
arcPath.addArc(
getWidth() / 2 - mRadius, getHeight() / 2 - mRadius,
getWidth() / 2 + mRadius, getHeight() / 2 + mRadius,
90 + remainAngle / 2,
360 - remainAngle
);
// 测量圆弧长度
PathMeasure pathMeasure = new PathMeasure(arcPath, false);
effect = new PathDashPathEffect(
// 用来绘制的path
dashPath,
// 两个相邻的path起点之间的间隔,如果不减去一个刻度宽的话,最后一个会画在紧按着圆弧的尾部,而不在圆弧上面
(pathMeasure.getLength() - UnitUtil.dp2px(2)) / (scaleCount - 1),
// 虚线的偏移
0,
// 旋转 一共三个值:TRANSLATE位移,MORPH变体
PathDashPathEffect.Style.ROTATE
);
}
@SuppressLint("NewApi")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 第一步:绘制弧线(没有封口的圆)
canvas.drawArc(
// 前四个参数是矩形的左上角右下角,给一个矩形范围,也就是圆的绘制范围
getWidth() / 2 - mRadius, getHeight() / 2 - mRadius,
getWidth() / 2 + mRadius, getHeight() / 2 + mRadius,
90 + remainAngle / 2, // 开始角度
360 - remainAngle, // 结束角度
false, // 是否闭合
mPaint
);
// 第二步:绘制刻度
mPaint.setPathEffect(effect);
canvas.drawArc(
getWidth() / 2 - mRadius, getHeight() / 2 - mRadius,
getWidth() / 2 + mRadius, getHeight() / 2 + mRadius,
90 + remainAngle / 2,
360 - remainAngle,
false,
mPaint
);
// 使用完之后恢复
mPaint.setPathEffect(null);
/*
第三步:画指针
Math.toRadians(将角度转换为弧度)
cos 余弦 (邻边/斜边)
sin 正弦 (对边/斜边)
最后再乘以斜边(pointerLength) 可得到邻边,对边长度
*/
canvas.drawLine(getWidth() / 2, getHeight() / 2,
(float) Math.cos(Math.toRadians(getAngleFromMark(mAngle))) * pointerLength + getWidth() / 2,
(float) Math.sin(Math.toRadians(getAngleFromMark(mAngle))) * pointerLength + getHeight() / 2,
mPaint);
}
private int getAngleFromMark(int mark) {
// 90°+ 下面剩余角度一半 + 刻度角度
return (int) (90 + (float) remainAngle / 2 + (360 - (float) remainAngle) / (scaleCount - 1) * mark);
}
}
来源:CSDN
作者:火炎焱燚-
链接:https://blog.csdn.net/Zheng_Jiao/article/details/103602491