调研发现了可以用于显示 商场门店示意图、建筑示意图、照片中物品摆放位置……的库
InDoorSurfaceView
作者博客
引入:
compile ‘com.github.karonl:InDoorSurfaceView:1.0’
库生产环境:
compileSdkVersion 24
minSdkVersion 16
使用解析
1)使用线程导入全局示意图,案例中是一个800kb的jpg文件,使用bitmap引入,设置为rgb_565
2)读取预设数据,确定点击位置
1、有个数据类:DataJson,其中有个json字符串保存着区域点击位置,比如:
String json = “{”_id":“570cf77757a46030037d4c30”,“areas”:" + “[ …… ]”;
其中省略部分的格式为: {“name”:"", “area”:"[]"}
{“name”:“H@M”,
“area”:[{“x”:387.1,“y”:392.1},{“x”:404.1,“y”:392.1},……}]},
2、获取原始数据:
JSONObject jsonObject = (JSONObject) jsonTokener.nextValue();
array = jsonObject.getJSONArray(“areas”);
其中array就是原始数据集合
获取图案列表
private void getUnitList() {
DataJson data = new DataJson();
for (int i = 0; i < data.size(); i++) {
JSONObject jsonObject = data.getArray(i);//原始数据集合
PathUnit unit = new PathUnit(getList(jsonObject));
try {
unit.setName(jsonObject.getString(“name”));
} catch (JSONException e) {
e.printStackTrace();
}
unitList.add(unit);
}
}
//单个点击区域的坐标集合处理,这个区域的圈定很复杂,有很多坐标点
private List getList(JSONObject jsonObject) {
float density = getResources().getDisplayMetrics().density;
List pointList = new ArrayList<>();
JSONArray array;
try {
array = jsonObject.getJSONArray(“area”);
for (int r = 0; r < array.length(); r++) {
float x = ((JSONObject) (array.get®)).getInt(“x”);
float y = ((JSONObject) (array.get®)).getInt(“y”);
pointList.add(new PointF(x * density, y * density));//像素化处理
}
} catch (JSONException e) {
e.printStackTrace();
}
return pointList;//返回单个点击区域的集合点
}
集合类PathUnit解析
public String name;
public String id;
public Region region; //点击事件发生时做范围判断
public Path path;//赋值时读取 List 绘制path线条(lineTo)确定区域
region的赋值复杂一点
RectF rectF = new RectF();
path.computeBounds(rectF, true);
region = new Region();
region.setPath(path, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom));
region的范围判断
private void clickMap(MotionEvent event) {
if (adapter != null)
for (PathUnit pathUnit : adapter.getPathUnit()) {
if (pathUnit.region.contains((int) ((event.getX() - bx) / scale), (int) ((event.getY() - by) / scale))) {
if (maplistener != null) maplistener.onClick(pathUnit);
}
}
}
点击监听
public boolean onTouch(View v, MotionEvent event) {
……
case MotionEvent.ACTION_UP:
if (mClick == CLICK) { //点击图案
clickMap(event);
drawThread.setCanPaint(false);//中止绘制
}
break;
……
}
InDoorView总结
该组件继承于SurfaceView,最核心的成分是处理onTouch,通过自定义的DrawThread线程处理绘图进度