腾讯地图SDK Android版开发 9 覆盖物示例3点聚合

前言

前文介绍了如何在地图上添加一个Overlay,本文重点介绍如何实现点聚合的功能。

  • 点聚合:当地图上需要展示的marker过多,可能会导致界面上marker压盖、性能变差。使用点聚合功能,则可以解决该问题。

相关的类和接口

配置

腾讯地图SDK点聚合部分位于com.tencent.tencentmap.mapsdk.vector.utils.clustering包中,因其依赖旧的 Android 支持库(Support Library),还没有迁移到 AndroidX。为了确保与 AndroidX 项目兼容,应启用 enableJetifier 属性。启用 enableJetifier 后,Gradle 在构建过程中会自动处理这些转换,确保项目能够正常编译和运行。

启用 enableJetifier 的方法

gradle.properties 文件,添加以下属性:

android.useAndroidX=true
android.enableJetifier=true
  • android.useAndroidX=true:表示项目使用 AndroidX 库。
  • android.enableJetifier=true:表示启用 Jetifier 工具,会自动将旧的支持库依赖项转换为 AndroidX 库依赖项。

点聚合

ClusterManager点聚合管理类主要接口如图:

image.png
接口 说明
ClusterManager(context, map) 构造
void setAlgorithm(algorithm) 设置聚合策略
void setRenderer(renderer) 设置聚合渲染器,默认使用的是DefaultClusterRenderer
void setOnClusterClickListener(onClusterClickListener) 设置点聚合单击事件
void setOnClusterItemClickListener(onClusterItemClickListener) 设置点聚合单个点对象单击事件
void addItems(items) 添加多个单个点对象
void clearItems() 删除所有单个点对象
void cluster() 重新聚合时调用,如更改聚合配置或刷新地图状态

示例

界面布局

1-布局.png
  • 布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MapMarkersActivity">

    <com.tencent.tencentmap.mapsdk.maps.TextureMapView
        android:id="@+id/mapview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@id/bottomView"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.appcompat.widget.LinearLayoutCompat
        android:id="@+id/bottomView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/mapview">

        <RadioGroup
            android:id="@+id/RadioGroup"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/background_dark"
            android:gravity="center_horizontal"
            android:orientation="horizontal"
            android:paddingHorizontal="10dp">

            <RadioButton
                android:id="@+id/cluster"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setMarkerFlag"
                android:text="点聚合"
                android:textColor="@color/white"
                android:textStyle="bold" />

            <RadioButton
                android:id="@+id/clear"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setMarkerFlag"
                android:text="清除"
                android:textColor="@color/white"
                android:textStyle="bold" />

        </RadioGroup>

    </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

MapMarks类

  • 以下是MapMarks部分代码。

常量

public static final String CLUSTER = "Cluster"; // 点聚合

成员变量

// 覆盖物列表
List<Removable> overlays = new ArrayList<>();
// 点聚合管理类
ClusterManager<MyClusterItem> clusterManager;

// 选中的状态
List<String> selectedFlags = new ArrayList<>();

初始化

  • 初始化点聚合管理类
// 实例化点聚合管理者并进行初始化
clusterManager = new ClusterManager<>(context, map);
// 默认聚合策略,调用时不必添加,如果需要其他聚合策略可以按以下代码修改
NonHierarchicalDistanceBasedAlgorithm<MyClusterItem> ndba =
        new NonHierarchicalDistanceBasedAlgorithm<>(context);
// 设置点聚合生效距离,以dp为单位
ndba.setMaxDistanceAtZoom(35);
// 设置策略
clusterManager.setAlgorithm(ndba);

// 设置聚合渲染器,默认使用的是DefaultClusterRenderer,可以不调用下列代码
DefaultClusterRenderer<MyClusterItem> renderer = new DefaultClusterRenderer<>(context,
        map, clusterManager);
// 设置最小聚合数量,默认为4,这里设置为2,即有2个以上不包括2个marker才会聚合
renderer.setMinClusterSize(2);
// 定义聚合的分段,当超过5个不足10个的时候,显示5+,其他分段同理
renderer.setBuckets(new int[]{5, 10, 20, 50});
clusterManager.setRenderer(renderer);

// 设置地图变换的监听接口
map.setOnCameraChangeListener(clusterManager);
selectedFlags.add(CLUSTER);

创建覆盖物

public void addMarkers() {
    if (selectedFlags.isEmpty())
        return;

    for (String flag : selectedFlags) {
        switch (flag) {
        case CLUSTER:
            addCluster();
            break;
        }
    }
}

点聚合

private void addCluster() {
    List<LatLng> points = new ArrayList<>();
    points.add(new LatLng(39.963175, 116.400244));
    points.add(new LatLng(39.942821, 116.369199));
    points.add(new LatLng(39.939723, 116.425541));
    points.add(new LatLng(39.906965, 116.401394));
    points.add(new LatLng(39.956965, 116.331394));
    points.add(new LatLng(39.886965, 116.441394));
    points.add(new LatLng(39.996965, 116.411394));

    List<MyClusterItem> items = new ArrayList<>();
    for (int i = 0; i < points.size(); i++) {
        // 创建覆盖物单个点对象
        items.add(new MyClusterItem(points.get(i)));
    }

    clusterManager.addItems(items);
    clusterManager.cluster();

    // 点击事件
    map.setOnMarkerClickListener(clusterManager);
    clusterManager.setOnClusterClickListener(new ClusterManager.OnClusterClickListener<MyClusterItem>() {
        @Override
        public boolean onClusterClick(Cluster<MyClusterItem> cluster) {
            showToast("有" + cluster.getSize() + "个点");
            return true;
        }
    });
    clusterManager.setOnClusterItemClickListener(new ClusterManager.OnClusterItemClickListener<MyClusterItem>() {
        @Override
        public boolean onClusterItemClick(MyClusterItem item) {
            showToast("点击单个Item");
            return true;
        }
    });
}
  • 实现ClusterItem
// ClusterItem接口的实现类
public static class MyClusterItem implements ClusterItem {
    LatLng position;

    public MyClusterItem(LatLng position) {
        this.position = position;
    }

    @Override
    public LatLng getPosition() {
        return position;
    }
}

移除覆盖物

public void removeOverlay() {
    // 清除地图上所有的标注类(Marker、Polyline、Polygon,TileOverlay除外)
    // map.clearAllOverlays();

    // 从地图移除覆盖物
    for (Removable overlay : overlays) {
        if (!overlay.isRemoved())
            overlay.remove();
    }
    overlays.clear();

    // 删除点聚合
    clusterManager.clearItems();
    clusterManager.cluster();
}

设置属性

public void setFlags(String flag) {
    selectedFlags.clear();
    if (flag != null)
        selectedFlags.add(flag);

    removeOverlay();
    addMarkers();
}

加载地图和移除地图

public void onMapLoaded() {
    addMarkers();
}

public void onMapDestroy() {
    removeOverlay();
}

MapMarkersActivity类

  • 以下是MapMarkersActivity类部分代码

控件响应事件

public void setMarkerFlag(View view) {
    boolean checked = ((RadioButton) view).isChecked();
    if (!checked)
        return;

    int id = view.getId();
    String flag;
    if (id == R.id.cluster)
        flag = MapMarkers.CLUSTER;
    else if (id == R.id.clear)
        flag = null;
    else
        return;

    mapMarkers.setFlags(flag);
}

运行效果图

3-点聚合1.png
3-点聚合2.png
3-点聚合3.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容