最近着手做一个新的项目,其中涉及到地图定位,以及从服务器获取附近的特定商家并在地图上面标注出来。于是就研究了一下百度地图标注覆盖物功能,然后进行一点个人总结,以便学习交流使用,个人学习总结还请各位看官轻喷。
百度地图SDK从2.0.0版本起,将定位功能进行了分离,开发者在使用过程中,下载开发包的时候注意下载带有定位功能的SDK。
定位功能的具体实现这里不过多赘述请参看官方文档;
核心代码如下:
/**
* 进行定位
*/
private void doLocation() {
Toast.makeText(this, "弹窗", Toast.LENGTH_SHORT).show();
mBaiduMap = mMapView.getMap();
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomTo(16));
locService = ((MyApplication) getApplication()).locationService;
LocationClientOption mOption = locService.getDefaultLocationClientOption();
mOption.setLocationMode(LocationClientOption.LocationMode.Battery_Saving);
mOption.setCoorType("bd09ll");
locService.setLocationOption(mOption);
locService.registerListener(listener);
locService.start();
}
/***
* 定位结果回调,在此方法中处理定位结果
*/
BDLocationListener listener = new BDLocationListener() {
@Override
public void onReceiveLocation(BDLocation location) {
if (location != null && (location.getLocType() == 161 || location.getLocType() == 66)) {
Message locMsg = locHander.obtainMessage();
Bundle locData = new Bundle();
locData.putParcelable("loc", location);
locMsg.setData(locData);
locHander.sendMessage(locMsg);
}
}
};
/***
* 接收定位结果消息,并显示在地图上
*/
private Handler locHander = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
try {
BDLocation location = msg.getData().getParcelable("loc");
if (location != null) {
LatLng point = new LatLng(location.getLatitude(), location.getLongitude());
// 构建Marker图标
BitmapDescriptor bitmap = null;
bitmap = BitmapDescriptorFactory.fromResource(R.drawable.bdmap_user_loaction);
// 构建MarkerOption,用于在地图上添加Marker
OverlayOptions option = new MarkerOptions().position(point).icon(bitmap);
// 在地图上添加Marker,并显示
mBaiduMap.addOverlay(option);
//设置地图新中心点
mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(point));
}
} catch (Exception e) {
// TODO: handle exception
}
}
};
以上代码就是开启定位功能并在地图上显示出来,其实已经用到了标注覆盖物功能。
标注覆盖物就是根据自己实际的业务需求,利用标注覆盖物,在地图指定的位置上添加标注信息。
效果如下:
//定义Maker坐标点
LatLng point = new LatLng(39.963175, 116.400244);
//构建Marker图标
BitmapDescriptor bitmap = BitmapDescriptorFactory
.fromResource(R.drawable.icon_marka);
//构建MarkerOption,用于在地图上添加Marker
OverlayOptions option = new MarkerOptions()
.position(point)
.icon(bitmap);
//在地图上添加Marker,并显示
mBaiduMap.addOverlay(option);
上述代码可以实现在地图上面特定位置标注出目标覆盖物的效果,但是在实际开发中有时候需要批量的添加这些覆盖物,并且要求能够实现对覆盖物的一些操作,这个时候仅仅这些代码是远远不够的。
首先是批量添加标注覆盖物,这里不得不吐槽一下百度地图的api,在升级3.0后api几乎全部不兼容。2.3的版本可以使用OverlayItem进行批量添加标注无,现在新版已经没有这个类了。所以首先想到的办法就是循环添加,其实也很简单,代码如下:
// 构建Marker图标
BitmapDescriptor bitmap = null;
bitmap = BitmapDescriptorFactory.fromResource(R.drawable.bdmap_user_loaction);
LatLng point =null;
//这里模拟出一些从服务器中获取到的坐标
double[][] testNum = {{34.826574, 113.569846}, {34.825322, 113.568809}, {34.825129, 113.570525}, {34.825163, 113.567695}, {34.826759, 113.570147}, {113.571935, 34.823474}, {34.823959, 113.575093}};
//模拟从服务器中获取到的商店信息
String[] shopName = {"no Name","万州烤鱼","君荷酒店","湘香烤鱼","圣禧牛肉汤","中国工商银行","莲花公园"};
Bundle bundle = new Bundle();
for (int i = 0;i"shopName",shopName[i]);
point = new LatLng(testNum[i][0],testNum[i][1]);
//.title()给覆盖物添加标题
OverlayOptions option = new MarkerOptions().position(point).icon(bitmap).title(shopName[i]);
mBaiduMap.addOverlay(option);
}
以上代码就是循环添加,实现起来很简单,但是有一个问题就是如果获取到的数据量很大的话,会很消耗相当的资源。
现在批量添加覆盖物实现了,还要求能像地图那样点击覆盖物能能弹出一些窗体或者一些其他操作,在官方文档中给出了一些对覆盖物的操作有拖拽、动画等,但是都不能很好的满足要求。于是查看了一些资料以后发现有一个mBaiduMap.setOnMarkerClickListener()方法,于是尝试着实现这个方法,实验发现要在标注覆盖物添加完成以后,再给mBaiduMap添加监听才可以,然后又出现一个问题就是如何才能从被点击的标注中获取到想要的信息,查看文档中并没有给出这些,查看所有类api文档发现有public MarkerOptions title(java.lang.String title)以及getTitle()方法,于是就将一些信息通过这个方法传入标注中。于是代码如下:
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
try {
BDLocation location = msg.getData().getParcelable("loc");
if (location != null) {
getNearbyShop(location.getLatitude(), location.getLongitude());
LatLng point = new LatLng(location.getLatitude(), location.getLongitude());
MaintelsLogUtils.outLog(location.getLatitude() + "_____" + location.getLongitude() + "");
// 构建Marker图标
BitmapDescriptor bitmap = null;
bitmap = BitmapDescriptorFactory.fromResource(R.drawable.bdmap_user_loaction);
// 构建MarkerOption,用于在地图上添加Marker
OverlayOptions option = new MarkerOptions().position(point).icon(bitmap);
// 在地图上添加Marker,并显示
mBaiduMap.addOverlay(option);
//设置地图新中心点
mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(point));
//添加标注覆盖物点击监听
mBaiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
String title = marker.getTitle();
if( title != null){
Toast.makeText(BDMapActivity.this, title, Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(BDMapActivity.this, "未知位置", Toast.LENGTH_SHORT).show();
}
return false;
}
});
}
} catch (Exception e) {
// TODO: handle exception
}
}
};
后来发现还有一个方法public MarkerOptions extraInfo(Bundle extraInfo),以bundle传入,待验证。