原理:利用百度地图的api,获取到行政区域的边界经纬度。然后依照在屏幕内的四个点(左上,左下,右上,右下):来判断边界和屏幕的关系,以此来控制地图位置。
效果,拖动地图,一旦自己定的区域范围离开屏幕,就重新确定地图的位置。
首先要获取到行政区域边界的经纬度。请参考百度地图api。或者Android【百度地图API,行政边界】关于百度地图显示行政边界问题_百度地图api去掉中国国界高亮显示-优快云博客这篇文章。
因为我们没必要每次都利用百度地图的api获取经纬度边界。所以,我想把它保留下来,保存为文件。以后直接读取文件的经纬度,岂不快哉。
坑一:记得调用下面的方法最好在mBaiduMap.setOnMapLoadedCallback();里面调用
坑二:如果不获取不到经纬度,画不出来看看是不是有mBaiduMap.clear();这个方法在做鬼。
注意:这个经纬度很多,log打印不全。最好的方法是在调试的时候,在AndroidStudio的logcat里面copy这个值,然后复制到txt文本里面。copy完之后的经纬度呢,嘿嘿,不能直接使用。然后把他变成json格式,然后推荐使用在线JSON校验格式化工具(Be JSON)。在打印log的时候有没有发现,polyline是分成多段的,这里我们也要分成多段。然后的json文件是这样的。我这里有个例子,大家可以看一下,也可以直接用https://download.youkuaiyun.com/download/u013778491/11750649。我这里的区域是南京江北新区的,所以这包含六合区和浦口区。是这样的:
有了这个文件,我们把他放到assent目录。
然后读取这个文件
public static String readLins(Context context) {
InputStream is = null;
try {
is = context.getResources().getAssets().open("js1.txt");
Reader in = new InputStreamReader(is);
BufferedReader bufferedReader = new BufferedReader(in);
String line = null;
StringBuilder stringBuilder = new StringBuilder();
while (null != (line = bufferedReader.readLine())) {
stringBuilder.append(line);
}
bufferedReader.close();
in.close();
is.close();
return stringBuilder.toString();
} catch (Exception e) {
}
return "";
}
这样以后每次就读取文件就可以画出边界线了。
private void DrawLines() {
String lins = FileUtil.readLins(instance);
try {
org.json.JSONArray jsonArray = new org.json.JSONArray(lins);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
List<LatLng> array1 = null;
for (int i = 0; i < jsonArray.length(); i++) {
org.json.JSONArray array = (org.json.JSONArray) jsonArray.get(i);
array1 = new ArrayList<>();
LatLng latLng = null;
for (int j = 0; j < array.length(); j++) {
org.json.JSONObject object = (org.json.JSONObject) array.get(j);
Double la = object.getDouble("latitude");
Double lo = object.getDouble("longitude");
latLng = new LatLng(la, lo);
array1.add(latLng);
builder.include(latLng);
line_poit.add(latLng);
}
PolylineOptions ooPolyline11 = new PolylineOptions().width(2)
.points(array1).dottedLine(true).color(Color.RED);
mBaiduMap.addOverlay(ooPolyline11);
}
mBaiduMap.setMapStatus(MapStatusUpdateFactory
.newLatLngBounds(builder.build()));
} catch (JSONException e) {
e.printStackTrace();
}
}
我们在画线的时候顺便把这些经纬度点都保存到集合里面line_poit。
然后在mBaiduMap.setOnMapStatusChangeListener()里面使用它
mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {
@Override
public void onMapStatusChangeStart(MapStatus mapStatus) {
}
@Override
public void onMapStatusChangeStart(MapStatus mapStatus, int i) {
}
@Override
public void onMapStatusChange(MapStatus mapStatus) {
}
@Override
public void onMapStatusChangeFinish(MapStatus mapStatus) {
// 地图看得见的地方的左上角坐标
Point point1 = new Point();
point1.x = 0;
point1.y = 0;// 状态栏高度加标题栏高度
// 地图看得见的地方的左下角坐标
Point point2 = new Point();
point2.x = 0;
int h = instance.getWindowManager().getDefaultDisplay().getHeight();
int w = instance.getWindowManager().getDefaultDisplay().getWidth();
point2.y = h;
// 地图看得见的地方的右上角坐标
Point point3 = new Point();
point3.x = w;
point3.y = 0;
// 地图看得见的地方的右下角坐标
Point point4 = new Point();
point4.x = w;
point4.y = h;
LatLng latlng1 = mBaiduMap.getProjection().fromScreenLocation(point1);
LatLng latlng2 = mBaiduMap.getProjection().fromScreenLocation(point2);
LatLng latlng3 = mBaiduMap.getProjection().fromScreenLocation(point3);
LatLng latlng4 = mBaiduMap.getProjection().fromScreenLocation(point4);
LatLngBounds.Builder b = new LatLngBounds.Builder();
b.include(latlng1);
b.include(latlng2);
b.include(latlng3);
b.include(latlng4);
LatLng latlng_center = b.build().getCenter();
boolean ok = false;
boolean hasone = false;
boolean hastwo = false;
boolean hasthree = false;
boolean hasfour = false;
if (line_poit.size() > 0) {
for (LatLng latLng : line_poit) {
Double la = latLng.latitude;
Double lo = latLng.longitude;
if (la > latlng2.latitude && la < latlng3.latitude && lo > latlng2.longitude && lo < latlng3.longitude) {
ok = true;
break;
}
}
if (!ok)
for (LatLng latLng : line_poit) {
Double la = latLng.latitude;
Double lo = latLng.longitude;
if (la > latlng_center.latitude && lo > latlng_center.longitude) {
hasone = true;
break;
}
}
if (!ok)
for (LatLng latLng : line_poit) {
Double la = latLng.latitude;
Double lo = latLng.longitude;
if (la < latlng_center.latitude && lo < latlng_center.longitude) {
hastwo = true;
break;
}
}
if (!ok)
for (LatLng latLng : line_poit) {
Double la = latLng.latitude;
Double lo = latLng.longitude;
if (la < latlng_center.latitude && lo > latlng_center.longitude) {
hasthree = true;
break;
}
}
if (!ok)
for (LatLng latLng : line_poit) {
Double la = latLng.latitude;
Double lo = latLng.longitude;
if (la > latlng_center.latitude && lo < latlng_center.longitude) {
hasfour = true;
break;
}
}
if (!ok) {
if (hasone && hastwo && hasthree && hasfour) {
} else {
LatLng ll = new LatLng(32.245193, 118.767211);
navigateTo(ll);
}
}
}
}
});
private void navigateTo(LatLng ll) {
mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(ll));
}
到此结束!!以下可以不看。
算法解释:有些情况下,我们不需要重新定位。比如
第一个图第二个图可以用if (la > latlng2.latitude && la < latlng3.latitude && lo > latlng2.longitude && lo < latlng3.longitude) { ok = true; break; }来判断,第三个图就有点麻烦了,因为会出现这样的情况。,所以才会有下面的几个判断。