结合自己的一些理解和整理   将Json数据格式 (只展现一部分 )中的经纬度 转化为 x,y 坐标 在Canvas 中画线

android 判断坐标在view内 android canvas坐标_i++

实现思路:

(1)首先根据一串经纬度中的最小的经度最小纬度创建坐标原点。

(2)根据设备屏幕大小与最大的经纬度差求得宽高比。

(3)格式化经纬度点,将其转为X Y坐标点。需要注意的是:安卓手机的坐标原点是手机的左上角,Y轴越往下数值越大,但是(北)纬度越往下越小,需要做绝对值转换;

1.布局文件   一定要设置id   这个就是Canvas  可以根据需求自己设定大小


android 判断坐标在view内 android canvas坐标_android_02

2.Activity

该activity主要处理经纬度数据、获取屏幕的宽高,具体的绘制过程在DrawView中。

代码简单贴一下:

(1)获取传来的经纬度数组【经度 纬度分开传输】;

(2)剔除数组里面为0.0的数据;如保证无此类数据,可删除此段代码;

(3)获取屏幕的宽高,这里可以自己根据上方 布局文件的  宽高 写成固定值 在下方有代码展示;

(4)实例化canvas,DrawView,将context,屏幕宽,屏幕高,纬度坐标数组,经度坐标数组)传进去;

(5)绘制组件

在点击事件中调用 initView  进行初始化 我这里的点击事件是响应item点击事件

private ContentAdapter.MyClickListener mListener = new ContentAdapter.MyClickListener() {
        @Override
        public void myOnClick(int position, View v) {
           initView((JSONArray) listItem.get(position).get("stations"));
        }
    };

或者最简单的点击调用

public void onClick(View v) {
        switch (v.getId()) {
             case R.id.charge:
               initView(输入的数据)
               }
        }
//jsonArray 为数据 就是你要传入的数据 我这里传入的是json数组   
private void initView(JSONArray jsonArray) {   
        RelativeLayout layout = (RelativeLayout) findViewById(R.id.can);
        DrawView views = new DrawView(this);
        views.setJsonArray(jsonArray);
        views.setMinimumHeight(500);
        views.setMinimumWidth(300);
        //通知view组件重绘
        views.invalidate();
        layout.addView(views);
    }

3.DrawView 主要的绘制工作在此View中进行

    3.1实例化 接收数据;

public class DrawView extends View {
    private JSONArray jsonArray;
    private double latData[] = null; //经纬度存放数据的数组
    private double lonData[] = null; //经纬度存放数据的数组
    private double latDataSort[];
    private double lotDataSort[];
    double lonOrigin;
    double latOrigin;
    double[] lonDataFormat;
    double[] latDataFormat;
    double maxWidth;
    double maxHeight;
    double heightRate;
    double widthRate;
    double screenHeight = 300; //画布的大小
    double screenWidth = 300;//画布的大小
    public void setJsonArray(JSONArray jsonArray) {
        this.jsonArray = jsonArray;
    }
    public DrawView(Context context) {
        super(context);
    }
    // 我在这里进行数据的 处理
    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setColor(Color.BLUE);
        latData = new double[jsonArray.length()];
        lonData = new double[jsonArray.length()];
        for (int i = 0; i < jsonArray.length(); i++) {
            try {
                JSONObject jsonObjK = new JSONObject(TcpClient.JSONTokener(jsonArray.get(i).toString()));
                latData[i] = (double) jsonObjK.get("lat");
                lonData[i] = (double) jsonObjK.get("lon");
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        pushData(canvas, paint);
    }

// 生成经纬度坐标点数据
    private void pushData(Canvas canvas, Paint p) {
        getMinLonLat();
        lonDataFormat = new double[lonData.length];
        latDataFormat = new double[latData.length];
        for (int i = 0; i < latData.length; i++) {
            latDataFormat[i] = yLatPointFormat(latData[i]);
        }
        for (int i = 0; i < lonData.length; i++) {
            lonDataFormat[i] = xLonPointFormat(lonData[i]);
        }
        latDataSort = latDataFormat;
        lotDataSort = lonDataFormat;
        getMaxWidth(lotDataSort);
        getMaxHeight(latDataSort);
        drawPolygon(canvas, p);
      //  drawPoint(canvas, p);

    }
//3.6 画线  
    private void drawPolygon(Canvas canvas, Paint p) {
        p.reset();
        p.setColor(Color.RED);
        p.setStrokeWidth(3);
        p.setStyle(Paint.Style.STROKE);
        Path path1 = new Path();
        double orgX = xLonPointFormat(lonOrigin);
        double orgY = yLatPointFormat(latOrigin);
        path1.moveTo((float) orgX, (float) orgY);
        float maginX=250;//x偏移量 设置 线整体 距离x 偏移  
        float maginY=50;//y偏移量
        float overSizeRata=1.8; // 线在图中缩放比例 线在Canvas显示不完整 根据需要调整
        for (int i = 0; i < lonDataFormat.length; i++) {
            double x = lonDataFormat[i] * widthRate/overSizeRata;
            double y = latDataFormat[i] * heightRate/overSizeRata;
            if (i == 0) {
                path1.moveTo((float) x+maginX, (float) y+maginY);
            } else {

                path1.lineTo((float) x+maginX, (float) y+maginY);
            }


        }
        path1.close();
        canvas.drawPath(path1, p);
    }


//获取最小的经纬度
    private void getMinLonLat() {
        double minLon = lonData[0];
        double maxLat = latData[0];
        for (int i = 0; i < lonData.length; i++) {
            if (minLon > lonData[i]) {
                minLon = lonData[i];
            }
        }
        for (int i = 0; i < lonData.length; i++) {
            if (maxLat < latData[i]) {
                maxLat = latData[i];
            }
        }
        lonOrigin = minLon;
        latOrigin = maxLat;
    }

//用经纬度减去最小经纬度,取绝对值 *10000(本项目中经纬度间隔较小,已实测间隔2M~1公里没啥问题如 
 果经纬度间隔较大,可调整10000这个数值的大小,根据我得经纬度 我调整为100000
    private Double xLonPointFormat(Double x) {
        x = Math.abs(x - lonOrigin) * 100000;
        x = Double.valueOf(Math.round(x * 100) / 100);
        return x;
    }

    private Double yLatPointFormat(Double y) {
        y = Math.abs(y - latOrigin) * 100000;
        y = Double.valueOf(Math.round(y * 100) / 100);
        return y;
    }

//获取坐标点最大经度差/纬度差与屏幕最大宽度/高度之间的比率
    private void getMaxWidth(double data[]) {
        double maxIndex = 0;
        double minIndex = 0;
        for (int i = 0; i < data.length; i++) {
            if (maxIndex < data[i]) {
                maxIndex = data[i];
            }
            if (minIndex > data[i]) {
                minIndex = data[i];
            }
        }
        maxWidth = (maxIndex - minIndex);
        if (Double.doubleToLongBits(maxWidth) == Double.doubleToLongBits(0.0)) {
            widthRate = 1;
        } else {
            widthRate = screenWidth / maxWidth;
        }

    }

    private void getMaxHeight(double data[]) {
        double maxIndex = 0;
        double minIndex = 0;
        for (int i = 0; i < data.length; i++) {
            if (maxIndex < data[i]) {
                maxIndex = data[i];
            }
            if (minIndex > data[i]) {
                minIndex = data[i];
            }
        }
        maxHeight = (maxIndex - minIndex);
        if (Double.doubleToLongBits(maxHeight) == Double.doubleToLongBits(0.0)) {
            heightRate = 1;
        } else {
            heightRate = screenHeight / maxHeight;
        }

    }
}

4 效果展示 

android 判断坐标在view内 android canvas坐标_json_03