终于到了UI绘制部分,个人还是比较感兴趣的,先从一些基本的入手。
先准备几个基本方法:
- dpToPixel()
public static float dpToPixel(float dp){
// 使用getSystem将无法获取APP本身的资源信息,但是获取系统的OK。
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dp,
Resources.getSystem().getDisplayMetrics());
}
首先draw()都是关于像素的方法,显然我们需要考虑手机的适配,所以以dp来进行绘图时很有必要的,上面就是一个dp转px的方法,值得注意的是,这里免去了像其他方法一样,需要传入context,这样让调用看着更舒服。
- canvas.drawArc()
public void drawArc(float left, float top, float right, float bottom,
float startAngle,float sweepAngle,
boolean useCenter,
Paint paint) {}
参数可以分为这么几类:
- 矩形范围,用于确定圆弧形状与尺寸的椭圆边界(即椭圆外切矩形)。
- 开始角度和扫描角度,从矩形正中出发,都是以时钟3点的方向为0°,顺时针为正方向。(3点钟这种理解起来可能比较怪,其实就是paint坐标系的x正方向)
- 是否包含圆心,最终绘制处理时弧还是扇形。
- 绘制圆弧的画笔
知道这两个,就能轻松绘制出一个弧形了。
看一下示例代码,以及相关注释:
public class DashboardView extends View {
private final static float ANGLE = 120;
private final static float RADIUS = UiUtils.dpToPixel(150);
private final static int DASH_NUM = 10;
private final static float POINT_LEN = UiUtils.dpToPixel(100);
/**
* 抗锯齿画笔
*/
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Path dash = new Path();
private PathDashPathEffect effect;
public DashboardView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
// 大括号里的方法,会在构造函数中super后执行,好处就是如果有多个构造函数的话,这里只用写一份。
{
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(UiUtils.dpToPixel(2));
// 确认刻度的大小、宽度
// 设置的left、top、right、bottom,这些都是相对path绘制路径的
dash.addRect(0, 0, UiUtils.dpToPixel(2), UiUtils.dpToPixel(10), Path.Direction.CCW);
// 计算路径的长度
Path arc = new Path();
arc.addArc(getWidth() / 2 - RADIUS, getHeight() / 2 - RADIUS,
getWidth() / 2 + RADIUS, getHeight() / 2 + RADIUS,
90 + ANGLE / 2, 360 - ANGLE);
PathMeasure measure = new PathMeasure(arc, false);
// 替换原paint的效果,同时计算出两个dash之间的间距,且预留好位置,以免出格
effect = new PathDashPathEffect(dash, (measure.getLength() - UiUtils.dpToPixel(2)) / DASH_NUM,
0, PathDashPathEffect.Style.ROTATE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 画线
canvas.drawArc(getWidth() / 2 - RADIUS, getHeight() / 2 - RADIUS,
getWidth() / 2 + RADIUS, getHeight() / 2 + RADIUS,
90 + ANGLE / 2, 360 - ANGLE, false, paint);
// 画刻度
paint.setPathEffect(effect);
canvas.drawArc(getWidth() / 2 - RADIUS, getHeight() / 2 - RADIUS,
getWidth() / 2 + RADIUS, getHeight() / 2 + RADIUS,
90 + ANGLE / 2, 360 - ANGLE, false, paint);
paint.setPathEffect(null);
// 画指针
// 启动时明确的,就是圆心,只需要确定目标点即可,通过三角函数来计算,其正方向也是X正方向出发,按顺时针来
canvas.drawLine(getWidth()/2,getHeight()/2,
getWidth()/2 + (float) Math.cos(Math.toRadians(getAngleFromMark(5)))*POINT_LEN,
getHeight()/2 + (float) Math.sin(Math.toRadians(getAngleFromMark(5)))*POINT_LEN,
paint);
}
// 根据具体的刻度位置,计算出一个角度
private int getAngleFromMark(int mark) {
return (int)(90 + ANGLE / 2 + (360 - ANGLE) / DASH_NUM * mark);
}
}
绘制效果:
仪表盘
总结:这块还是比较简单的,注意下绘制使用的一些套路即可。
网友评论