有段时间没有更新了,还是那句话,忙是其一,懒是主因(自嘲一下。。)
最近因项目需要,在app中添加了地图的点聚合功能,用的是百度地图,查过文档,看过源码,功能实现了,记录一下。
效果图:
下面来介绍一下实现:
额,对。。。第一步,需要先到百度地图下载SDK,这个就不介绍了。
下面步入正题:
百度的点聚合是对外开放源码的。我们需要在百度提供的demo中把clusterutil整个目录拷贝到自己的工程里面。
其中,接口Cluster,对应的是一个聚合点。接口ClusterItem,对应的是聚合点中的每一项。另,如果地图当前缩放的层级没有达到聚合的要求(当然,这个聚合的逻辑判断,百度已经帮我们写好了),显示在页面上的每一个marker都是一个ClusterItem的实现。
运行demo的时候,我们发现,demo中只是实现了点聚合的功能,各种点击事件都没有。查看代码,发现ClusterManager(顾名思义就是Cluster的管理类)中有设置相应的点击事件。
mClusterManager.setOnClusterClickListener(new OnClusterClickListener<BaiduNearbyActivity.MyItem>(){
@Override
public boolean onClusterClick(Cluster<MyItem> cluster){
// TODO Auto-generated method stub
return false;
}});
mClusterManager.setOnClusterItemClickListener(new OnClusterItemClickListener<BaiduNearbyActivity.MyItem>(){
@Override
public boolean onClusterItemClick(MyItem item){
// TODO Auto-generated method stub
return false;
}});
分别对应Cluster和ClusterItem的点击事件。然后把事件的监听交给mClusterManager。
mBaiduMap.setOnMarkerClickListener(mClusterManager);
但是,添加之后还是没有响应。原来百度在ClusterManager和DefaultClusterRenderer中,接口调用的地方没有写,给我留了个TODO。需要我们自己修改
ClusterManager类: 中
public void setOnClusterItemClickListener(OnClusterItemClickListener<T> listener) {
mOnClusterItemClickListener = listener;
mRenderer.setOnClusterItemClickListener(listener);
}
DefaultClusterRenderer类: 中
public void setOnClusterItemClickListener(ClusterManager.OnClusterItemClickListener<T> listener) {
mItemClickListener = listener;
}
这样在运行,发现点击事件可以正常响应了。
功能实现了,就需要我们根据实际需要改一下样式。记得前边提到的ClusterItem吗?
我们需要自己来实现ClusterItem接口,来定义自己的样式。
/**
* 每个Marker点,包含Marker点坐标以及图标
*/
public class MyItem implements ClusterItem{
private final LatLng mPosition;
private String mType;
private String mName;
public MyItem(LatLng latLng, HashMap<String, String> map){
mPosition = latLng;
mType = map.get("type");
mName = map.get("name");
}
@Override
public LatLng getPosition(){
return mPosition;
}
@Override
public BitmapDescriptor getBitmapDescriptor(){
// 吃
if ("1".equals(mType)){
return BitmapDescriptorFactory
.fromResource(R.drawable.map_fandian);
// 喝
}else if ("2".equals(mType)){
return BitmapDescriptorFactory
.fromResource(R.drawable.map_kafei);
// 玩
}else if ("3".equals(mType)){
return BitmapDescriptorFactory
.fromResource(R.drawable.map_huadian);
// 乐
}else if ("4".equals(mType)){
return BitmapDescriptorFactory.fromResource(R.drawable.map_le);
}else{
return BitmapDescriptorFactory
.fromResource(R.drawable.icon_gcoding_own_loc);
}
}
}
到此,就可以实现上面效果图的样式了。
在加一个功能点,点击后弹出个视图。显示详细信息。
先上图:
百度提供了覆盖物的功能,可以实现上面效果,但是貌似自定义view做起来不太好实现。(当然,本人才疏学浅,有人有好的解决方案,欢迎留言交流)
额。。最近总捣鼓一句话:招都是人想出来的,那没办法,想办法实现吧。
我的实现方式是在地图上层中间偏上的位置加一个隐藏的view,就是上面的样式。(至于显示一条两条的方法,我就不往出贴了,免得献丑)然后,当点击上面的点时,把当前点移动到地图view的中间,百度对这个实现提供了动画效果,还不错,不用自己写了。然后,当聚合点的点数过多的话,只增大地图的缩放等级,不显示隐藏的视图,至于几个才显示,就自己控制了。下面贴代码.
// 将地图移到到当前点击经纬度位置 并增加缩放等级
mBaiduMap.animateMapStatus(MapStatusUpdateFactory
.newMapStatus(new MapStatus.Builder()
.zoom(mBaiduMap.getMapStatus().zoom + 1)
.target(cluster.getPosition())
.build()));