Android 自定义View----仪表盘

↘锁芯ラ 提交于 2019-12-19 04:23:07

通过这个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);
    }
    
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!