Android google maps marker clustering

Google Maps clustering

Если вы занимаетесь разработкой приложений, использующих Google Maps, то вполне можете столкнуться с ситуацией, изображенной на картинке слева. И, если вы считаете, что картинка справа выглядит лучше, то вам сюда.

Итак, какие проблемы возникают при работе с большим количеством маркеров:

  • При количестве маркеров >5000-10000 карта начинает жестоко тормозить.
  • Внешний вид карты, заполненной маркерами, совсем не радует глаз.

Какое же существует решение этой проблемы? Ответ — кластеризация. Кластер — объединение нескольких однородных элементов, которое может рассматриваться как самостоятельная единица, обладающая определёнными свойствами. Соответственно, мы должны объединять маркеры по территориальному признаку и заменять их одним маркером. И, к счастью, все это уже реализовано.

Помимо стандартной библиотеки для работы с картами, Google предоставляет замечательную библиотеку Google Maps Android Marker Clustering Utility. Эта библиотека поставляется отдельно и позволяет компоновать маркеры.

Рассмотрим наиболее сложный пример, когда у есть несколько типов маркеров, каждый со своей иконкой и необходимыми действиями по нажатию (например, вывод InfoWindow с текстом).

Задача

Пусть перед нами поставлена следующая задача: дана торговая сеть, у нее есть некоторое количество точек и большое количество грузовиков, перевозящих товар, которые способны отчитываться о своем местоположении. Нужно наладить мониторинг положения грузовиков и торговых точек. У маркеров грузовиков должна быть иконка с лицом водителя. Заказчик суровый, увидел картинку с кластерами и сказал, чтобы все было так, а не иначе.

Шаг 1. Подготовка

Первый шаг весьма логичен — нужно описать абстрактный класс маркера, от которого будут наследоваться все остальные. Чтобы возможно было использовать кластеризацию, этот класс маркера должен уметь возвращать свое местоположение. Для этого необходимо реализовать интерфейс ClusterItem. Тогда возможный код абстрактного класса:

Далее находится не слишком важный код классов маркеров торговых точек и грузовиков, но вдруг кому-то интересно.

Шаг 2. Простейшая кластеризация

Что же, подготовка завершена, теперь пора настроить кластеризацию. Наиболее важным здесь является класс ClusterManager, который позволяет гибко настроить кластеризацию. Класс ClusterManager является обобщенным, в качестве параметра ему передается класс, реализующий интерфейс ClusterItem. В качестве параметров при инициализации ему подаются контекст приложения и объект GoogleMap.

Таким образом, для нашего кода это будет выглядеть примерно так:

И теперь остается только добавить маркеры в этот объект с помощью метода clusterManager.addItem(AbstractMarker marker);.

С помощью метода cluster объекта класса ClusterManager можно вызвать рекластеризацию (например, после добавления элементов). Чтобы автоматически вызывать этот метод при изменении положения камеры (при изменении приближения) необходимо присвоить карте обработчик OnCameraChangeListener.

Что же, теперь наша карта почти красивая. Почему почти? Потому что вместо фотографий водителей, вы увидите только маркеры по умолчанию не исключено, что так будет лучше, а по нажатию на маркер ничего не будет происходить, даже если написали InfoWindowAdapter. Вот теперь и будем улучшать внешний вид, пользуясь предоставляемыми средствами.

Шаг 3. Алгоритм

Рассмотрим алгоритмы кластеризации. Существуют различные алгоритмы, можно выделить 2 основных:

Grid-based Clustering — видимая область карты делится на квадраты, в центр квадрата помещается один кластер.

  • Поддерживает удаление элементов.
  • Работает достаточно быстро.
  • Выглядит не очень красиво, но если маркеры распределены равномерно, то ничего плохого в этом алгоритме нет

Distance-based Clustering — алгоритм по умолчанию. Основывается на вычисление центров наибольшей концентрации маркеров; кластеры не имеют фиксированных границ.

  • Не поддерживает удаление элементов.
  • Работает медленнее (более сложные вычисления).
  • Красиво располагает маркеры в соответствии с положением на карте.
Читайте также:  Драконы всадники олуха для андроида

Надеюсь, Google не обидится на меня за взятые с документации картинки.

Вряд ли появится существенная нужда писать собственный алгоритм, но если уж сильно хочется, то вам придется реализовать интерфейс Algorithm.

Шаг 4. Изменение свойств объекта clusterManager

Как я сказал, фотографии наших водителей сменились на стандартные маркеры. Не порядок. К счастью, это легко исправить (и не только это). У объекта clusterManager есть метод setRenderer, который позволяет задать класс, который будет управлять кластерами / маркерами перед выводом на карту и многое другое. По умолчанию используется класс DefaultClusterRenderer, в котором многие фишки уже реализованы правильно. Поэтому наилучшим подходом будет унаследоваться от этого класса и переопределить нужные методы:

И присвоим нашему clusterManager этот класс:

Мне нужно только поменять иконку у маркеров, поэтому я переопределил только метод onBeforeClusterItemRendered, который позволяет настроить элементы кластеров перед выводом на карту. Но выбор методов для переопределения достаточно велик:

Просто как отдельный факт, в процессе кластеризации немаловажную роль играет класс MarkerManager, который по сути предоставляет интерфейс для работы с коллекцией маркеров и кластеров.

И давайте сделаем последний штрих: по нажатию на маркер будем стандартно выводить информацию о текущем маркере с помощью метода toString (мы его переопределяли), а по нажатию на кластер будем выводить, сколько торговых точек и грузовиков находятся в этом регионе.
Во-первых, нам понадобятся объекты выбранных маркера и кластера:

Необходимо добавить listeners к clusterManager:

Нужно также сделать clusterManager слушателем события OnMarkerClickListener:

Теперь необходимо присвоить InfoWindowAdapter всем маркерам и всем кластерам. Для этого можно воспользоваться методами получения коллекций кластеров маркеров у объекта clusterManager. Также не забудем присвоить InfoWindowAdapter карте:

Ну и для примера как может выглядеть класс ClusterInfoWindow:

Таким образом, мы создали красивую и достаточно функциональную карту.

Надеюсь, данная статья была для вас полезной. Она является лишь результатом изучения библиотеки и личных изысканий, поэтому ссылки на ресурсы оставлять не буду. Спасибо, что дочитали до конца!

Источник

Google Maps Android Marker Clustering Utility

By clustering your markers, you can put a large number of markers on a map without making the map hard to read.

Introduction

This video discusses the use of marker clustering when your data requires a large number of data points on the map.

The marker clustering utility helps you manage multiple markers at different zoom levels. To be precise, the ‘markers’ are actually ‘items’ at this point, and only become ‘Markers’ when they’re rendered. But for the sake of clarity, this document will name them ‘markers’ throughout.

When a user views the map at a high zoom level, the individual markers show on the map. When the user zooms out, the markers gather together into clusters, to make viewing the map easier. The marker clustering utility is part of the Maps SDK for Android Utility Library. If you haven’t yet set up the library, follow the setup guide before reading the rest of this page.

Clustered markers

To use the marker clustering utility, you will need to add markers as ClusterItem objects to the ClusterManager . The ClusterManager passes the markers to the Algorithm , which transforms them into a set of clusters. The ClusterRenderer takes care of the rendering, by adding and removing clusters and individual markers. The ClusterRenderer and Algorithm are pluggable and can be customized.

The utility library ships with a demo app providing sample implementations of the marker clustering utility. For help with running the demo app, see the setup guide. The demo app includes the following marker clustering samples:

  • ClusteringDemoActivity : A simple activity demonstrating marker clustering.
  • BigClusteringDemoActivity : Clustering with 2 000 markers.
  • CustomMarkerClusteringDemoActivity : Creating a custom design for clustered markers.
Читайте также:  Как сделать будильник по нарастающей андроид

Add a simple marker clusterer

Follow the steps below to create a simple cluster of ten markers. The result will look like this, although the number of markers shown/clustered will change depending on the zoom level:

Ten clustered markers

Here is a summary of the steps required:

  1. Implement ClusterItem to represent a marker on the map. The cluster item returns the position of the marker as a LatLng object, and an optional title or snippet.
  2. Add a new ClusterManager to group the cluster items (markers) based on zoom level.
  3. Set the map’s OnCameraIdleListener() to the ClusterManager , since ClusterManager implements the listener.
  4. If you want to add specific functionality in response to a marker click event, set the map’s OnMarkerClickListener() to the ClusterManager , since ClusterManager implements the listener.
  5. Feed the markers into the ClusterManager .

Looking at the steps in more detail: To create our simple cluster of ten markers, first create a MyItem class that implements ClusterItem .

Kotlin

In your map activity, add the ClusterManager and feed it the cluster items. Note the type argument , which declares the ClusterManager to be of type MyItem .

Kotlin

You can also choose to disable the clustering animations when zooming in and out. If animation is turned off, the markers snap into position instead of migrating in and out of the clusters. To disable animations, use setAnimation() in ClusterManager as shown below:

Kotlin

Add an info window for an individual clustered marker

To add an info window for specific clustered markers, add title and snippet strings into the constructor of your implementation of ClusterItem .

The following example adds a marker with an info window in the addItems() method, by setting a title and snippet:

Kotlin

Customize the marker clusters

The ClusterManager constructor creates a DefaultClusterRenderer and a NonHierarchicalDistanceBasedAlgorithm . You can change the ClusterRenderer and the Algorithm using the setAlgorithm(Algorithm algorithm) and setRenderer(ClusterRenderer view) methods of ClusterManager .

You can implement ClusterRenderer to customize the rendering of the clusters. DefaultClusterRenderer provides a good base to start from. By subclassing DefaultClusterRenderer , you can override the defaults.

For an in-depth example of customization, take a look at CustomMarkerClusteringDemoActivity in the demo app that ships with the utility library.

Custom clustered markers

The CustomMarkerClusteringDemoActivity defines its own cluster item, a Person , and renders it by extending the DefaultClusterRenderer as PersonRenderer .

The demo also shows how to implement the ClusterManager.OnClusterClickListener

interface to display more information about the person when the cluster is clicked. You can also implement ClusterManager.OnClusterItemClickListener

in a similar way.

For help with running the demo app, see the setup guide.

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Источник

Утилита для кластеризации маркеров Google Карт на Android

Кластеризация маркеров позволяет добавить на карту большое количество маркеров без ухудшения ее удобочитаемости.

Введение

В этом видеоролике рассказывается о кластеризации маркеров, которая требуется в случае, если на карте нужно отобразить много данных одновременно.

Утилита для кластеризации маркеров позволяет управлять несколькими маркерами на разных уровнях масштабирования. При этом маркеры фактически обрабатываются как объекты, а отрисовываются как маркеры. Однако для ясности в этой статье всегда используется термин «маркеры».

Когда пользователь просматривает карту в большом масштабе, на ней отображаются отдельные маркеры. При уменьшении масштаба маркеры собираются в кластеры, что упрощает чтение карты. Утилита для кластеризации маркеров входит в состав библиотеки утилит Maps SDK для Android. Если вы ещё не настроили эту библиотеку, выполните рекомендации из руководства по настройке, прежде чем продолжить чтение этой страницы.

Читайте также:  Все про root андроид

Кластеризованные маркеры

Чтобы воспользоваться утилитой кластеризации маркеров, необходимо добавить маркеры в виде объектов ClusterItem в ClusterManager . ClusterManager передает маркеры в Algorithm , который преобразует их в набор кластеров. ClusterRenderer отвечает за прорисовку, добавляя и удаляя кластеры и отдельные маркеры. Классы ClusterRenderer и Algorithm являются подключаемыми модулями и их можно настраивать.

В комплект библиотеки утилит входит демонстрационное приложение, в котором приведены примеры реализации утилиты для кластеризации маркеров. О том, как запустить демонстрационное приложение, рассказывается в руководстве по настройке. Демонстрационное приложение включает в себя следующие примеры кластеризации маркеров:

  • ClusteringDemoActivity – простая операция, демонстрирующая кластеризацию маркеров.
  • BigClusteringDemoActivity – кластеризация 2000 маркеров.
  • CustomMarkerClusteringDemoActivity – создание собственного макета для кластеризованных маркеров.

Как добавить простое средство кластеризации маркеров

Чтобы создать простой кластер, состоящий из 10 маркеров, выполните описанные ниже действия. Результат будет иметь следующий вид, хотя количество отображаемых и кластеризованных маркеров будет изменяться в зависимости от уровня масштабирования:

10 кластеризованных маркеров

Ниже перечислены шаги, которые необходимо выполнить.

  1. Реализуйте класс ClusterItem для представления маркеров на карте. Объект кластера возвращает позицию маркера в виде объекта LatLng. Он также может возвращать название или фрагмент (необязательно).
  2. Добавьте новый объект ClusterManager , группирующий объекты кластеров (маркеры) с учетом уровня масштабирования.
  3. Свяжите метод OnCameraIdleListener() карты с объектом ClusterManager . Это нужно сделать, потому что в ClusterManager реализован прослушиватель.
  4. Если вы хотите добавить функции, активируемые при клике по маркеру, нужно связать метод OnMarkerClickListener() карты с объектом ClusterManager , поскольку в ClusterManager реализован прослушиватель.
  5. Передайте маркеры объекту ClusterManager .

Подробные инструкции. Чтобы создать простой кластер из десяти маркеров, сначала создайте класс MyItem , реализующий ClusterItem .

Kotlin

В операции, работающей с картой, добавьте ClusterManager и передайте ему объекты кластеров. Обратите внимание на аргумент типа , декларирующий ClusterManager как относящийся к типу MyItem .

Kotlin

Вы также можете отключить анимацию кластеров при увеличении и уменьшении масштаба. Если анимация отключена, маркеры мгновенно перемещаются на нужные позиции, а не передвигаются в кластеры или из кластеров. Чтобы отключить анимацию, используйте метод setAnimation() в ClusterManager , как показано здесь:

Kotlin

Как добавить информационное окно для отдельного кластеризованного маркера

Чтобы добавить информационное окно для конкретных кластеризованных маркеров, добавьте строки title (название) и snippet (фрагмент) в конструктор вашего класса ClusterItem .

В следующем примере показано, как реализовать в методе addItems() добавление маркера с информационным окном, задав значения полей title и snippet:

Kotlin

Как настроить кластеры маркеров

Конструктор класса ClusterManager создает объекты DefaultClusterRenderer и NonHierarchicalDistanceBasedAlgorithm . Вы можете изменить ClusterRenderer и Algorithm с помощью методов setAlgorithm(Algorithm algorithm) и setRenderer(ClusterRenderer view) класса ClusterManager .

Вы можете реализовать ClusterRenderer , чтобы изменить настройки отображения кластеров. В качестве исходного макета рекомендуется использовать DefaultClusterRenderer . Создав подкласс на основе DefaultClusterRenderer , вы можете изменить настройки по умолчанию.

Подробный пример настройки представлен в операции CustomMarkerClusteringDemoActivity демонстрационного приложения из библиотеки утилит.

Маркеры с настраиваемой кластеризацией

В CustomMarkerClusteringDemoActivity определяется объект кластера Person и реализуется его отрисовка за счет наследования класса DefaultClusterRenderer как PersonRenderer .

В демонстрационном приложении также показано, как реализовать интерфейс ClusterManager.OnClusterClickListener

для отображения дополнительной информации о человеке (элементе Person) при клике по кластеру. Вы также можете реализовать ClusterManager.OnClusterItemClickListener

О том, как запустить демонстрационное приложение, рассказывается в руководстве по настройке.

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Источник

Оцените статью