1、准备工作
地图的显示及定位参考我的上两篇博客,本篇实现通过POI获取区域边界坐标并添加覆盖物的功能
2、布局文件
在之前的基础上添加手动显示覆盖物的按钮
<Button
android:id="@+id/weilan"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_marginTop="60dp"
android:background="@color/white"
android:text="围"/>
3、主代码
这里的代码为之前基础上添加后的全部代码
public class map_content extends Fragment{
private View view;
private ImageView dingwei;
private Button weilan;
private TextureMapView mMapView = null;
private BaiduMap mBaiduMap = null;
private LocationClient mLocationClient = null;
//防止每次定位都重新设置中心点和marker
private boolean isFirstLocation = true;
//注册LocationListener监听器
MyLocationListener myLocationListener = new MyLocationListener();
//经纬度
private double lat;
private double lon;
//POI实例
private PoiSearch poiSearch;
public static Fragment newInstance(){
map_content mapContent = new map_content();
return maptContent;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//在使用SDK各组件之前初始化context信息,传入ApplicationContext
SDKInitializer.initialize(getActivity().getApplicationContext());
//自4.3.0起,百度地图SDK所有接口均支持百度坐标和国测局坐标,用此方法设置您使用的坐标类型.
//包括BD09LL和GCJ02两种坐标,默认是BD09LL坐标。
SDKInitializer.setCoordType(CoordType.BD09LL);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.wuye_xqjs_xqdt,null);
init();
mBaiduMap = mMapView.getMap();
mBaiduMap.setMyLocationEnabled(true);//开启地图的定位图层
initMap();
return view;
}
private void init(){
mMapView = view.findViewById(R.id.bmapView);
dingwei = view.findViewById(R.id.dingwei);
weilan = view.findViewById(R.id.weilan);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
dingwei.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLocationClient.requestLocation();
LatLng ll =new LatLng(lat,lon);
MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);
mBaiduMap.animateMapStatus(u);
mBaiduMap.setMapStatus(u);
MapStatusUpdate u1 = MapStatusUpdateFactory.zoomTo(16f); //缩放
mBaiduMap.animateMapStatus(u1);
}
});
weilan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
searchInCity("此处传入要搜索的区域具体地址名,如中国地质大学(北京)");
}
});
}
@Override
public void onResume() {
super.onResume();
//在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
isFirstLocation = true;//每次重新进入Fragement时修改为true,保证能够显示中心点
searchInCity("此处传入要搜索的区域具体地址名,如中国地质大学(北京)");//每次重新进入Fragment时自动执行一次POI并显示覆盖物,若自动显示失败,则需手动点击按钮显示区域覆盖物
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
//每次切换到其他Fragment时销毁定位,防止黑屏
mLocationClient.unRegisterLocationListener(myLocationListener);
mLocationClient.stop();
// 关闭定位图层
mBaiduMap.setMyLocationEnabled(false);
//在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理
mMapView.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
//在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
// 退出时销毁定位
mLocationClient.unRegisterLocationListener(myLocationListener);
mLocationClient.stop();
// 关闭定位图层
mBaiduMap.setMyLocationEnabled(false);
mMapView.onDestroy();
mMapView = null;
}
public class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//mapView 销毁后不在处理新接收的位置
if (location == null || mMapView == null){
return;
}
lat = location.getLatitude();
lon = location.getLongitude();
MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(location.getDirection())
.latitude(location.getLatitude())
.longitude(location.getLongitude()).build();
//这个判断是为了防止每次定位都重新设置中心点和marker
if (isFirstLocation) {
isFirstLocation = false;
//设置并显示中心点
mBaiduMap.setMyLocationData(locData);
}
}
}
public void initMap(){
//定位初始化
mLocationClient = new LocationClient(getActivity().getApplicationContext());
//通过LocationClientOption设置LocationClient相关参数
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打开gps
option.setCoorType("bd09ll"); // 设置坐标类型
option.setScanSpan(1000);
//设置locationClientOption
mLocationClient.setLocOption(option);
mLocationClient.registerLocationListener(myLocationListener);
//开启地图定位图层
mLocationClient.start();
//定位图标样式,采用默认图标,不显示精度外圈
MyLocationConfiguration myLocationConfiguration = new MyLocationConfiguration(MyLocationConfiguration.LocationMode.FOLLOWING,true,(BitmapDescriptor)null);
myLocationConfiguration.accuracyCircleFillColor = 0x00000000;
myLocationConfiguration.accuracyCircleStrokeColor = 0x00000000;
mBaiduMap.setMyLocationConfiguration(myLocationConfiguration);
//poi实例
poiSearch = PoiSearch.newInstance();
}
/**
*通过传参的形式进行城市POI,不知道为什么只有通过传参的形式输入具体地址名才能检索到,直接在keyword("")中放地址名很难检索出来
*/
public void searchInCity(String keyword){
// 设置检索参数
PoiCitySearchOption citySearchOption = new PoiCitySearchOption();
citySearchOption.city("北京");// 城市
citySearchOption.keyword(keyword);// 关键字
citySearchOption.pageCapacity(15);// 默认每页10条
citySearchOption.pageNum(0);// 分页编号
//搜索监听
poiSearch.setOnGetPoiSearchResultListener(poiSearchListener);
// 为PoiSearch设置搜索方式.
poiSearch.searchInCity(citySearchOption);
}
OnGetPoiSearchResultListener poiSearchListener = new OnGetPoiSearchResultListener() {
// 获取poiResult
@Override
public void onGetPoiResult(PoiResult poiResult) {
if (poiResult.error == SearchResult.ERRORNO.NO_ERROR) {
List<PoiInfo> poiList = poiResult.getAllPoi();
String uid = poiList.get(0).uid;
//通过uid进行地址访问,获取返回的json数据,捕获区域坐标
String address = "http://map.baidu.com/?pcevaname=pc4.1&qt=ext&ext_ver=new&l=12&uid="+uid;
//根据uid地址获取坐标
HttpUtils.sendRequestWithOkhttp(address, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String points = HttpUtils.parseJsonWithJsonObject(response);
//边界点
List<String[]> pointList = coordinateChange(points);
//中心点
List<Double> centerPoint = getCenterPoint(points);
addPolygon(pointList,centerPoint);
}
});
}else {
Toast.makeText(getContext(),""+poiResult.error,Toast.LENGTH_SHORT).show();
//因为每次进入地图自动POI时,总会POI失败受到PERMISSION_UNFINISHED错误返回信息,所以我的解决方法是一旦受到错误信息,就再POI一次,为了防止OOM建议大家加上次数限制
searchInCity(current_com);
}
}
// 当点击覆盖物的时候,查询详细的数据信息,作为回调返回数据信息
@Override
public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
}
@Override
public void onGetPoiDetailResult(PoiDetailSearchResult poiDetailSearchResult) {
}
@Override
public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {
}
};
/**
* 区域边界坐标提取
* @param mipoint
* @return
*/
public List<String[]> coordinateChange(String mipoint){
String[] points1 = mipoint.split("-");
String[] points2 = points1[1].replace(";","").split(",");
List<String[]> points3 = new ArrayList<String[]>();
for(int i=0;i<points2.length;i++){
String[] temps = new String[2];
temps[0] = points2[i];
temps[1] = points2[i+1];
points3.add(temps);
i++;
}
return points3;
}
/**
*提取区域中心点
*/
public List<Double> getCenterPoint(String points){
String[] points1 = points.split("-");
String[] points2 = points1[0].split(";");//4|123243.4,54534.5 12334.5,323435.4|1
String[] points3 = points2[0].split("\\|");//4 123243.4,54534.5
String[] points4 = points2[1].split("\\|");//12334.5,323435.4 1
String[] points5 = points3[1].split(",");//123243.4 54534.5
String[] points6 = points4[0].split(",");//12334.5 323435.4
Double x = (Double.valueOf(points5[0])+Double.valueOf(points6[0]))/2;
Double y = (Double.valueOf(points5[1])+Double.valueOf(points6[1]))/2;
List<Double> center = new ArrayList<Double>();
center.add(x);
center.add(y);
return center;
}
/**
* 添加多边形覆盖物
* @param list
*/
public void addPolygon(List<String[]> list,List<Double> center){
//多边形顶点位置
List<LatLng> points = new ArrayList<>();
//因为获取到的坐标的墨卡托坐标,是米制坐标,需要转换成百度经纬度坐标
for(int i=0;i<list.size();i++){
Double lng = Double.valueOf(list.get(i)[0]);
Double lat = Double.valueOf(list.get(i)[1]);
LatLng sourceLatLng = new LatLng(lat,lng);
// sourceLatLng待转换坐标
CoordinateConverter converter = new CoordinateConverter()
.from(CoordinateConverter.CoordType.BD09MC)
.coord(sourceLatLng);
LatLng point = converter.convert();
points.add(point);
}
//构造PolygonOptions
PolygonOptions mPolygonOptions = new PolygonOptions()
.points(points)
.fillColor(0x5500CCFF) //填充颜色
.stroke(new Stroke(5, 0xFFFF3300)); //边框宽度和颜色
mBaiduMap.addOverlay(mPolygonOptions);
//处理区域中心点坐标
LatLng sourceLatLng1 = new LatLng(center.get(1),center.get(0));
// sourceLatLng待转换坐标
CoordinateConverter converter1 = new CoordinateConverter()
.from(CoordinateConverter.CoordType.BD09MC)
.coord(sourceLatLng1);
LatLng centerPoint = converter1.convert();
//缩放到围栏区域
mLocationClient.requestLocation();
MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(centerPoint);
mBaiduMap.animateMapStatus(u);
mBaiduMap.setMapStatus(u);
MapStatusUpdate u1 = MapStatusUpdateFactory.zoomTo(17f); //缩放
mBaiduMap.animateMapStatus(u1);
}
}
4、网络处理工具代码
使用的框架是okhttp3
在builde.gradle(Module:app)中的dependencies中添加:
implementation 'com.squareup.okhttp3:okhttp:3.4.1'
工具类代码:
public class HttpUtils {
public static void sendRequestWithOkhttp(String address, Callback callback){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(address).build();
client.newCall(request).enqueue(callback);
}
public static String parseJsonWithJsonObject(Response response) throws IOException{
String responseData = response.body().string();
String geo = null;
//具体的json数据解析请视自己收到的json数据组成而定
try {
JSONObject result = new JSONObject(responseData);
JSONObject content = result.getJSONObject("content");
geo = content.getString("geo");
}catch (JSONException e){
e.printStackTrace();
}
return geo;
}
}