官网实例请点击:Android 高德地图聚合官网
下面是一个案例:
效果图:
MainActivity
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
private MapView mapView;
private AMap aMap;
/**
* 地图初始化比例尺,地图比例尺
*/
public static float ORGZOON = 12;
/**
* 数据列表
*/
private List<DotInfo> dotList = new ArrayList<>();
/**
* marker数据集合
*/
public Map<String, Marker> markerMap = new ConcurrentHashMap<>();
public static final int MARKER_NORMA = 1;
public static final int MARKER_TOGE = 2;
public static int markerStatus = MARKER_NORMA;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapView = (MapView) findViewById(R.id.map);
mapView.onCreate(savedInstanceState);// 此方法必须重写
init();
}
/**
* 初始化AMap对象
*/
private void init() {
if (aMap == null) {
aMap = mapView.getMap();
aMap.moveCamera(CameraUpdateFactory.zoomTo(ORGZOON));
}
aMap.setOnCameraChangeListener(onCameraChangeListener);
dotList.clear();
dotList = DotInfo.initData();
}
/**
* 设置地图移动监听
*/
private AMap.OnCameraChangeListener onCameraChangeListener = new AMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition cameraPosition) {
}
@Override
public void onCameraChangeFinish(CameraPosition cameraPosition) {
// 放大缩小完成后对聚合点进行重新计算
updateMapMarkers();
}
};
private synchronized void updateMapMarkers() {
if (dotList != null && dotList.size() > 0) {
Log.i(TAG, "地图级别:" + aMap.getCameraPosition().zoom);
// 若当前地图级别小于初始化比例尺,则显示聚合网点
if (aMap.getCameraPosition().zoom < 7) {
markerStatus = MARKER_TOGE;
updateTogMarkers();
}
// 显示普通marker
else {
if (markerStatus == MARKER_TOGE) {
markerStatus = MARKER_NORMA;
updateNormalMarkers();
}
}
System.gc();
}
}
/**
* 更新普通网点数据
*/
private void updateNormalMarkers() {
// 判断上一次更新marker操作的操作类型,若上次显示的是聚合网点,则先清空地图,然后清空网点信息,在刷新地图marker
aMap.clear();
markerMap.clear();
loadMarker(DotInfo.initData());
}
/**
* 更新聚合网点
*/
private void updateTogMarkers() {
Log.i(TAG, "开始显示聚合网点,清空地图normal marker...");
aMap.clear();
// 更新聚合marker
MapTogetherManager.getInstance(this, aMap).onMapLoadedUpdateMarker(markerMap);
// 设置marker点击事件,若是聚合网点此时点击marker则放大地图显示正常网点
aMap.setOnMarkerClickListener(new AMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
// 初始化地图按指定的比例尺移动到定位的坐标
aMap.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition(marker.getPosition(), ORGZOON, 3, 0)), 1000, null);
return true;
}
});
}
private void updateGetMarkers() {
Log.e(TAG, "");
aMap.clear();
MapTogetherManager.getInstance(this, aMap).onMapLoadedUpdateMarker(markerMap);
}
/**
* 初始化marker数据
*/
private void loadMarker(List<DotInfo> dotList) {
if (dotList == null || dotList.size() == 0) {
return;
}
for (int i = 0; i < dotList.size(); i++) {
DotInfo dotInfo = dotList.get(i);
MarkerOptions options = new MarkerOptions();
options.anchor(0.5f, 1.0f);
options.position(new LatLng(dotInfo.getDotLat(), dotInfo.getDotLon()));
setIconToOptions(options);
Marker marker = aMap.addMarker(options);
marker.setObject(dotInfo);
marker.setZIndex(ORGZOON);
markerMap.put(dotInfo.getDotId(), marker);
}
}
/**
* 为marker的Options设置icon
*
* @param options
*/
private void setIconToOptions(MarkerOptions options) {
ImageView view = new ImageView(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(21, 27, 1);
view.setImageResource(R.mipmap.blue_location);
view.setLayoutParams(params);
view.setScaleType(ImageView.ScaleType.FIT_XY);
options.icon(BitmapDescriptorFactory.fromView(view));
}
/**
* 方法必须重写
*/
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
updateNormalMarkers();
}
/**
* 方法必须重写
*/
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
/**
* 方法必须重写
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
/**
* 方法必须重写
*/
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
}
MapTogetherManager
public class MapTogetherManager {
public static final String TAG = MapTogetherManager.class.getSimpleName();
private int CLUSTER_SIZE = 100;// 地图上距离小于多少个像素点,则合并
private int DRAWABLE_RADIUS = 80;// 聚合网点的显示大小,drawable的radius大小
private static Map<String, TogDotInfo> togDotInfoMap;// 聚合网点列表
private static Map<String, Marker> togMarkerMap;// 聚合网点marker
private Activity mContext;
private AMap aMap;
public static MapTogetherManager instance = null;
public static MapTogetherManager getInstance(Activity mContext, AMap aMap) {
if (instance == null) {
instance = new MapTogetherManager(mContext, aMap);
}
return instance;
}
private MapTogetherManager(Activity mContext, AMap aMap) {
this.mContext = mContext;
this.aMap = aMap;
togDotInfoMap = new ConcurrentHashMap<String, TogDotInfo>();
togMarkerMap = new ConcurrentHashMap<String, Marker>();
}
// ########### 设置当地图加载完成事件 start ######################
Object lockObject = new Object();
/**
* 更新聚合网点
*/
public void onMapLoadedUpdateMarker(final Map<String, Marker> markerMap) {
// 清空内存聚合网点数据
togDotInfoMap.clear();
togMarkerMap.clear();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (lockObject) {
Log.e(TAG, "开始循环遍历,执行网点聚合操作...");
Iterator<Map.Entry<String, Marker>> iterator = markerMap.entrySet().iterator();
// 循环遍历在已有的聚合基础上,对添加的单个元素进行聚合
while (iterator.hasNext()) {
assignSingleCluster(iterator.next().getValue());
}
Log.e(TAG, "开始执行将聚合网点展示在地图上...");
// 将聚合的网点现在在地图上
if (togDotInfoMap != null && togDotInfoMap.size() > 0) {
Iterator<Map.Entry<String, TogDotInfo>> cIterator = togDotInfoMap.entrySet().iterator();
while (cIterator.hasNext()) {
Map.Entry<String, TogDotInfo> togMap = cIterator.next();
addTogDotInfoToMap(togMap.getKey(), togMap.getValue());
}
}
}
}
}).start();
}
/**
* 在已有的聚合基础上,对添加的单个元素进行聚合
*/
private void assignSingleCluster(Marker marker) {
DotInfo dotInfo = (DotInfo) marker.getObject();
LatLng latLng = new LatLng(dotInfo.getDotLat(), dotInfo.getDotLon());
Point point = aMap.getProjection().toScreenLocation(latLng);
TogDotInfo togDotInfo = getCluster(point);
if (togDotInfo != null) {
togDotInfo.addClusterItem(marker);
// 更新聚合网点个数
togDotInfo.setDotCount(togDotInfo.getDotCount() + 1);
} else {
togDotInfo = new TogDotInfo(point, latLng);
// 更新聚合网点个数
togDotInfo.setDotCount(1);
togDotInfo.addClusterItem(marker);
togDotInfoMap.put(dotInfo.getDotId() + SystemClock.currentThreadTimeMillis(), togDotInfo);
}
}
/**
* 将聚合网点添加至地图显示
* @param togDotInfo 需要更新的聚合网点对象
*/
private void addTogDotInfoToMap(String dotId, TogDotInfo togDotInfo) {
LatLng latlng = togDotInfo.getCenterLatLng();
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.anchor(0.5f, 0.5f).icon(getBitmapDes(togDotInfo)).position(latlng);
Marker marker = aMap.addMarker(markerOptions);
togMarkerMap.put(dotId, marker);
}
/**
* 获取每个聚合点的绘制样式
**/
private BitmapDescriptor getBitmapDes(final TogDotInfo togDotInfo) {
TextView textView = new TextView(mContext);
String tile = String.valueOf(togDotInfo.getDotCount());
textView.setText(tile + "");
textView.setGravity(Gravity.CENTER);
textView.setTextColor(Color.BLACK);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15);
textView.setBackgroundDrawable(getDrawAble(togDotInfo.getDotCount()));
togDotInfo.setTextView(textView);
return BitmapDescriptorFactory.fromView(textView);
}
/**
* 根据一个点获取是否可以依附的聚合点,没有则返回null
* @param point
* @return
*/
private TogDotInfo getCluster(Point point) {
Iterator<Map.Entry<String, TogDotInfo>> cIterator = togDotInfoMap.entrySet().iterator();
while (cIterator.hasNext()) {
TogDotInfo togDotInfo = cIterator.next().getValue();
Point poi = togDotInfo.getCenterPoint();
double distance = getDistanceBetweenTwoPoints(point.x, point.y, poi.x, poi.y);
if (distance < CLUSTER_SIZE) {
return togDotInfo;
}
}
return null;
}
/**
* 计算地图上两个点之间的距离
* @return
*/
private double getDistanceBetweenTwoPoints(double x1, double y1, double x2,
double y2) {
double distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2)
* (y1 - y2));
return distance;
}
/**
* 获取聚合网点显示的Drawable
* @param clusterNum
* @return
*/
public Drawable getDrawAble(int clusterNum) {
int radius = DisplayUtil.dip2px(mContext, DRAWABLE_RADIUS);
// 根据不同的网点个数,显示不同的聚合网点drawable
// if (clusterNum < 5) {
BitmapDrawable drawable = new BitmapDrawable(drawCircle(radius,
Color.argb(159, 210, 154, 6)));
return drawable;
/*} else if (clusterNum < 10) {
BitmapDrawable drawable = new BitmapDrawable(drawCircle(radius,
Color.argb(199, 217, 114, 0)));
return drawable;
} else {
BitmapDrawable drawable = new BitmapDrawable(drawCircle(radius,
Color.argb(235, 215, 66, 2)));
return drawable;
}*/
}
/**
* 获取聚合网点显示的圆框
* @param radius
* @param color
* @return
*/
private Bitmap drawCircle(int radius, int color) {
Bitmap bitmap = Bitmap.createBitmap(radius * 2, radius * 2,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
RectF rectF = new RectF(0, 0, radius * 2, radius * 2);
paint.setColor(color);
canvas.drawArc(rectF, 0, 360, true, paint);
return bitmap;
}
// ########### 设置当地图加载完成事件 end ######################
}
TogDotInfo
**
* 聚合网点信息列表用于保存聚合网点信息
*/
class TogDotInfo {
private Point mPoint;// 中心网点
private LatLng mLatLng;// 中心网点经纬度
private List<Marker> mClusterItems;// 网点列表
private int dotCount;// 网点个数
private TextView textView;// 聚合网点显示
TogDotInfo(Point point, LatLng latLng) {
mPoint = point;
mLatLng = latLng;
mClusterItems = new ArrayList<>();
}
void addClusterItem(Marker clusterItem) {
mClusterItems.add(clusterItem);
}
Point getCenterPoint() {
return mPoint;
}
LatLng getCenterLatLng() {
return mLatLng;
}
public int getDotCount() {
return dotCount;
}
public void setDotCount(int dotCount) {
this.dotCount = dotCount;
}
public List<Marker> getmClusterItems() {
return mClusterItems;
}
public TextView getTextView() {
return textView;
}
public void setTextView(TextView textView) {
this.textView = textView;
}
}
DotInfo
public class DotInfo {
private String dotId;
private double dotLat;
private double dotLon;
public String getDotId() {
return dotId;
}
public void setDotId(String dotId) {
this.dotId = dotId;
}
public double getDotLat() {
return dotLat;
}
public void setDotLat(double dotLat) {
this.dotLat = dotLat;
}
public double getDotLon() {
return dotLon;
}
public void setDotLon(double dotLon) {
this.dotLon = dotLon;
}
/**
* 初始化数据
* @return
*/
public static List<DotInfo> initData() {
List<DotInfo> dotInfoList = new ArrayList<>();
DotInfo dotInfo1 = new DotInfo();
dotInfo1.setDotLat(39.976318);
dotInfo1.setDotLon(116.318988);
dotInfo1.setDotId("dotInfo1");
dotInfoList.add(dotInfo1);
DotInfo dotInfo2 = new DotInfo();
dotInfo2.setDotLat(40.045813);
dotInfo2.setDotLon(116.304504);
dotInfo2.setDotId("dotInfo2");
dotInfoList.add(dotInfo2);
DotInfo dotInfo3 = new DotInfo();
dotInfo3.setDotLat(39.923347);
dotInfo3.setDotLon(116.507537);
dotInfo3.setDotId("dotInfo3");
dotInfoList.add(dotInfo3);
DotInfo dotInfo4 = new DotInfo();
dotInfo4.setDotLat(39.91125);
dotInfo4.setDotLon(116.477378);
dotInfo4.setDotId("dotInfo4");
dotInfoList.add(dotInfo4);
DotInfo dotInfo5 = new DotInfo();
dotInfo5.setDotLat(40.041337);
dotInfo5.setDotLon(116.312181);
dotInfo5.setDotId("dotInfo5");
dotInfoList.add(dotInfo5);
DotInfo dotInfo6 = new DotInfo();
dotInfo6.setDotLat(39.971879);
dotInfo6.setDotLon(116.306446);
dotInfo6.setDotId("dotInfo6");
dotInfoList.add(dotInfo6);
DotInfo dotInfo7 = new DotInfo();
dotInfo7.setDotLat(40.002434);
dotInfo7.setDotLon(116.463232);
dotInfo7.setDotId("dotInfo7");
dotInfoList.add(dotInfo7);
DotInfo dotInfo8 = new DotInfo();
dotInfo8.setDotLat(39.980959);
dotInfo8.setDotLon(116.331772);
dotInfo8.setDotId("dotInfo8");
dotInfoList.add(dotInfo8);
DotInfo dotInfo9 = new DotInfo();
dotInfo9.setDotLat(39.925659);
dotInfo9.setDotLon(116.508567);
dotInfo9.setDotId("dotInfo9");
dotInfoList.add(dotInfo9);
DotInfo dotInfo10 = new DotInfo();
dotInfo10.setDotLat(39.88543);
dotInfo10.setDotLon(116.461778);
dotInfo10.setDotId("dotInfo10");
dotInfoList.add(dotInfo10);
DotInfo dotInfo11 = new DotInfo();
dotInfo11.setDotLat(39.98343);
dotInfo11.setDotLon(116.311843);
dotInfo11.setDotId("dotInfo11");
dotInfoList.add(dotInfo11);
DotInfo dotInfo12 = new DotInfo();
dotInfo12.setDotLat(40.029849);
dotInfo12.setDotLon(116.313302);
dotInfo12.setDotId("dotInfo12");
dotInfoList.add(dotInfo12);
return dotInfoList;
}
}
DisplayUtil
public class DisplayUtil {
public static int screenWidthPx; //屏幕宽 px
public static int screenhightPx; //屏幕高 px
public static float density;//屏幕密度
public static int densityDPI;//屏幕密度
public static float screenWidthDip;// dp单位
public static float screenHightDip;// dp单位
public static int statusBarHight;
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 将px值转换为sp值,保证文字大小不变
*
* @param pxValue (DisplayMetrics类中属性scaledDensity)
* @return
*/
public static int px2sp(Context context, float pxValue) {
final float fontScale = context.getResources().getDisplayMetrics()
.scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
/**
* 将sp值转换为px值,保证文字大小不变
*
* @param spValue (DisplayMetrics类中属性scaledDensity)
* @return
*/
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics()
.scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
}
xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.test_map_pio.MainActivity">
<com.amap.api.maps.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
一些基础配置这里就不在介绍,如有什么不足,请指出。