android 自定义View 绘制图形

  老样子,先说下背景,最近做的一个音视频通话,要求对端画箭头、矩形,圆圈,android端能及时画出来,研究了半天,不得不说,有同事的帮助,,感谢我的同事给予我的帮助,让我学习了不少,现在总结一下 我的工作

首先自定义view 绘制,主要是在onDraw方法里面通过view的 invalidate()重绘方法去执行的,另有一个postinvalidate()是在子线程执行,这个区别我就不介绍了,自行查找一堆。。

 先来看看我的自定义View类吧

/**
 * Created by Jane on 2019/2/21.
 */
public class DrawView extends View {
    private final String TAG = "DrawView";
    private String jsonInfo;

    public String getJsonInfo() {
        return jsonInfo;
    }

    public void setJsonInfo(String jsonInfo) {
        this.jsonInfo = jsonInfo;
    }


    public DrawView(Context context) {
        super(context);
    }

    public DrawView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public DrawView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /*
         * 方法 说明 drawRect 绘制矩形 drawCircle 绘制圆形 drawOval 绘制椭圆 drawPath 绘制任意多边形
         * drawLine 绘制直线 drawPoin 绘制点
         */
        // 创建画笔

        String jsonInfo = getJsonInfo();
        try {
            if (!TextUtils.isEmpty(jsonInfo)) {
                JSONObject json_info = new JSONObject(jsonInfo);
                if (json_info.has("rectangle")) {
                    parseData(canvas, json_info, "rectangle");
                }  if (json_info.has("circle")) {
                    Log.e("sssss","circlr==");
                    parseData(canvas, json_info, "circle");
                }  if (json_info.has("arrow")) {
                    parseData(canvas, json_info, "arrow");
                }  if (json_info.has("dot")) {
                    JSONObject jsonDot=new JSONObject(json_info.optString("dot"));
                    int canvasX = ScreenUtils.getScreenWidth();
                    int canvasY = ScreenUtils.getScreenHeight();
                    float finX = Float.parseFloat(jsonDot.optInt("finl_X")+"");
                    float finY = Float.parseFloat(jsonDot.optInt("final_Y")+"");
                    int cavX = jsonDot.optInt("canvas_X");
                    int cavY = jsonDot.optInt("canvas_Y");
                    Log.e("sssss","鼠标值==finX=="+finX+"----finY=="+finY);
                    if (cavX!=0&&cavY!=0){
                        float cX = canvasX / cavX;
                        float cY = canvasY / cavY;
                        float fX = finX * cX;
                        float fY = finY * cY;
                        drawMouse(canvas, fX, fY, p);
                    }

                }

            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解析数据
     */
    public void parseData(Canvas canvas, JSONObject jsonInfo, String type) {
        int canvasX = ScreenUtils.getScreenWidth();
        int canvasY = ScreenUtils.getScreenHeight();
        try {
            JSONArray jsonArrayR = new JSONArray(jsonInfo.optString(type));
            for (int i = 0; i < jsonArrayR.length(); i++) {
                JSONObject jsonObjectR = jsonArrayR.optJSONObject(i);
                float finX = Float.parseFloat(jsonObjectR.optString("finl_X"));
                float finY = Float.parseFloat(jsonObjectR.optString("final_Y"));
                int cavX = jsonObjectR.optInt("canvas_X");
                int cavY = jsonObjectR.optInt("canvas_Y");
                float startX = Float.parseFloat(jsonObjectR.optString("start_X"));
                float startY = Float.parseFloat(jsonObjectR.optString("start_Y"));
                String color = jsonObjectR.optString("color");
                int lineWidth = jsonObjectR.optInt("lineWidth");
                createPaint(color, lineWidth);
                float cX = canvasX / cavX;
                float cY = canvasY / cavY;
                float sX = startX * cX;
                float sY = startY * cY;
                float fX = finX * cX;
                float fY = finY * cY;
                if (type.equals("circle")) {
                    drawCircle(sX, sY, fX, fY, canvas, p);//圆圈
                }  if (type.equals("rectangle")) {
                    canvas.drawRect(sX, sY, fX, fY, p);//矩形
                }  if (type.equals("arrow")) {
                    drawAL(canvas, p, sX, sY, fX, fY);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    /**
     * 创建画笔
     **/
    Paint p = new Paint();

    public void createPaint(String color, int lineWidth) {

        /*
         * 方法 说明 drawRect 绘制矩形 drawCircle 绘制圆形 drawOval 绘制椭圆 drawPath 绘制任意多边形
         * drawLine 绘制直线 drawPoin 绘制点
         */
        // 创建画笔
        if (!TextUtils.isEmpty(color)) {
            p.setColor(Color.parseColor(color));
        } else {
            p.setColor(Color.parseColor("#0000FF"));// 设置默认颜色
        }
        p.setStyle(Paint.Style.STROKE);//设置空心
        p.setStrokeWidth(lineWidth);
    }

    /*画圆
     *
     * **/
    public void drawCircle(float sX, float sY, float fX, float fY, Canvas canvas, Paint p) {
        //算出圆心坐标 起点+终点坐标除以2
        //半径 起点-终点坐标除以2
        float centerX = (sX + fX) / 2;
        float centerY = (sY + fY) / 2;
        float rx = (sX - fX) / 2;
        float ry = (sY - fY) / 2;
        float r = Float.parseFloat(Math.sqrt(rx * rx + ry * ry) + "");
        canvas.drawCircle(centerX, centerY, r, p);// 大圆
    }

    /**
     * 画箭头
     *
     * @param sx
     * @param sy
     * @param ex
     * @param ey
     */
    public void drawAL(Canvas canvas, Paint paint, float sx, float sy, float ex, float ey) {
        double H = 8; // 箭头高度
        double L = 3.5; // 底边的一半
        int x3 = 0;
        int y3 = 0;
        int x4 = 0;
        int y4 = 0;
        double awrad = Math.atan(L / H); // 箭头角度
        double arraow_len = Math.sqrt(L * L + H * H); // 箭头的长度
        double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
        double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
        double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端点
        double y_3 = ey - arrXY_1[1];
        double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端点
        double y_4 = ey - arrXY_2[1];
        Float X3 = new Float(x_3);
        x3 = X3.intValue();
        Float Y3 = new Float(y_3);
        y3 = Y3.intValue();
        Float X4 = new Float(x_4);
        x4 = X4.intValue();
        Float Y4 = new Float(y_4);
        y4 = Y4.intValue();
        // 画线
        canvas.drawLine(sx, sy, ex, ey, paint);
        Path triangle = new Path();
        triangle.moveTo(ex, ey);
        triangle.lineTo(x3, y3);
        triangle.lineTo(x4, y4);
        triangle.close();
        canvas.drawPath(triangle, paint);
    }

    /**
     * 图片固定点
     */
    Bitmap bitmap = null;

    public void drawMouse(Canvas canvas, float x, float y, Paint paint) {
        //画图片,就是贴图
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mouse);
        canvas.drawBitmap(bitmap, x, y, paint);
    }

    // 计算
    public double[] rotateVec(float px, float py, double ang, boolean isChLen, double newLen) {
        double mathstr[] = new double[2];
        // 矢量旋转函数,参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度
        double vx = px * Math.cos(ang) - py * Math.sin(ang);
        double vy = px * Math.sin(ang) + py * Math.cos(ang);
        if (isChLen) {
            double d = Math.sqrt(vx * vx + vy * vy);
            vx = vx / d * newLen;
            vy = vy / d * newLen;
            mathstr[0] = vx;
            mathstr[1] = vy;
        }
        return mathstr;
    }

    public void clear(Canvas canvas) {
        Paint p = new Paint();
        //清屏
        p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawPaint(p);
        p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
    }


}

不难看出,这里面有参考别的小伙伴的,我也不求能涨个粉丝,只是为了让自己长知识,首先说一下遇到过的问题,需求是:绘制的矩形、圆圈、箭头 是多个,出现了一个bug就是,每次绘制的时候 ,只有最新的,之前的都自动清除,原因是,每次调用invalidate()方法,onDraw方法里面是if else 只会执行其中的一个,所以会把之前清除的自动刷新掉,只怪自己当时不明白,同事给我讲了一通。。我也是后知后觉的。。。

知道问题之后,就要想办法解决的哦,既然每次调用invalidate()都会重绘,那我能不能把之前每次收到的数据统一放入一个json中,将矩形、圆圈、箭头分别分成三个数组,绘制的时候遍历数组,逐一绘制呢,目前就是按照这种思路去写的。。

,为避免drawview重复创建 要判空的哦,,要不,画一个 创建一个对象,清除的时候会发现只清除了最后一次绘制的图形

以上就是这次的;理解,真的没说太好,,,大概就这样,有问题 一起交流哈

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值