绘制基础(一)- 仪表盘绘制

终于到了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);
    }
}

绘制效果:


仪表盘

总结:这块还是比较简单的,注意下绘制使用的一些套路即可。

你可能感兴趣的:(绘制基础(一)- 仪表盘绘制)