有段時間沒有更新了,還是那句話,忙是其一,懶是主因(自嘲一下。。)
最近因項目需要,在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()));