Fast marker clustering library for Google Maps Android API.

Overview

Google Maps Clustering for Android

Download Android Arsenal

A fast marker clustering library for Google Maps Android API.

Demo

Motivation

Why not use Google Maps Android API Utility Library? Because it's very slow for large amounts of markers, which causes skipping frames and ANRs (see Issue #29, Issue #82). But this library can easily handle thousands of markers (the video above demonstrates the sample application with 20 000 markers running on Nexus 5).

Installation

  1. Make sure you have JCenter in your repository list:
repositories {
    jcenter()
}
  1. Add a dependency to your build.gradle:
dependencies {
    compile 'net.sharewire:google-maps-clustering:0.1.3'
}

Integration

  1. Implement ClusterItem to represent a marker on the map. The cluster item returns the position of the marker and an optional title or snippet:
class SampleClusterItem implements ClusterItem {

    private final LatLng location;

    SampleClusterItem(@NonNull LatLng location) {
        this.location = location;
    }

    @Override
    public double getLatitude() {
        return location.latitude;
    }

    @Override
    public double getLongitude() {
        return location.longitude;
    }

    @Nullable
    @Override
    public String getTitle() {
        return null;
    }

    @Nullable
    @Override
    public String getSnippet() {
        return null;
    }
}
  1. Create an instance of ClusterManager and set it as a camera idle listener using GoogleMap.setOnCameraIdleListener(...):
ClusterManager<SampleClusterItem> clusterManager = new ClusterManager<>(context, googleMap);
googleMap.setOnCameraIdleListener(clusterManager);
  1. To add a callback that's invoked when a cluster or a cluster item is clicked, use ClusterManager.setCallbacks(...):
clusterManager.setCallbacks(new ClusterManager.Callbacks<SampleClusterItem>() {
            @Override
            public boolean onClusterClick(@NonNull Cluster<SampleClusterItem> cluster) {
                Log.d(TAG, "onClusterClick");
                return false;
            }

            @Override
            public boolean onClusterItemClick(@NonNull SampleClusterItem clusterItem) {
                Log.d(TAG, "onClusterItemClick");
                return false;
            }
        });
  1. To customize the icons create an instance of IconGenerator and set it using ClusterManager.setIconGenerator(...). You can also use the default implementation DefaultIconGenerator and customize the style of icons using DefaultIconGenerator.setIconStyle(...).

  2. Populate ClusterManager with items using ClusterManager.setItems(...):

List<SampleClusterItem> clusterItems = generateSampleClusterItems();
clusterManager.setItems(clusterItems);
Comments
  • [Question] Set custom marker icon?

    [Question] Set custom marker icon?

    Hi, first of all, thank you for you contribution. I tried the original library by Google and, yes, it's slow. So I found yours! But I'm having some trouble making things work. I have a custom marker, made like this:

    @Override
    public void onMapReady(GoogleMap map) {
          final IconGenerator iconFactory = new IconGenerator(this);
               iconFactory.setStyle(IconGenerator.STYLE_BLUE);
        
        addIcon(iconFactory, "9872", locationExample); 
    }
    private void addIcon(IconGenerator iconFactory, CharSequence text, LatLng position) {
            MarkerOptions markerOptions = new MarkerOptions().
                    icon(BitmapDescriptorFactory.fromBitmap(iconFactory.makeIcon(text))).
                    position(position).
                    anchor(iconFactory.getAnchorU(), iconFactory.getAnchorV());
    
            map.addMarker(markerOptions);
    

    And now I'm trying to add your cluster library to it, but I dont know if I can use my already customized markers. If not, does your library have a custom marker icon option? I've tried to do it, but I can't get it work. Could you please give me an example of a custom marker? I just need a marker with a number inside.

    This was my best try:

    final ClusterManager<SampleClusterItem> clusterManager = new ClusterManager<>(this, map);
            clusterManager.setCallbacks(new ClusterManager.Callbacks<SampleClusterItem>() {
                @Override
                public boolean onClusterClick(@NonNull Cluster<SampleClusterItem> cluster) {
                    Log.d(TAG, "onClusterClick");
                    return false;
                }
    
                @Override
                public boolean onClusterItemClick(@NonNull SampleClusterItem clusterItem) {
                    Log.d(TAG, "onClusterItemClick");
                    return false;
                }
            });
            map.setOnCameraIdleListener(clusterManager);
    
            IconStyle.Builder stilo = new IconStyle.Builder(this);
            stilo.setClusterBackgroundColor(Color.BLUE);
            stilo.setClusterTextColor(Color.WHITE);
    
            DefaultIconGenerator icono = new DefaultIconGenerator(this);
            icono.setIconStyle(stilo.build());
    

    Thank you so much :)

    question 
    opened by carlosmacmar 15
  • Cluster range / min cluster size

    Cluster range / min cluster size

    Hey, thank you for writing this library - google maps utils really lacks maintainers...

    I wonder if it's possible to change the range of the clusters. I've just seen the screenshots and the clusters seem very far apart.

    Thanks in advance.

    opened by meierjan 8
  • Modifying Library in Existing App

    Modifying Library in Existing App

    @makovkastar I need to modify some of the library classes such as QuadTree so I can pass additional variables to ClusterItem, but it says that the library is read only since I imported it with gradle.

    So I followed guides trying to import it as a module, but always got build errors such as Error:(11, 0) Could not find method compile() for arguments [project ':subProject:library'] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler. <a href="openFile:C:\Users\Nathan\Android Projects\ImportModule4\build.gradle">Open File</a>

    and

    Error:(18, 0) Could not find method android() for arguments [build_enfbvdz6abztfoiqie2qzfmjg$_run_closure1@58eced6f] on root project 'ModuleImport2' of type org.gradle.api.Project. <a href="openFile:C:\Users\Nathan\Android Projects\ModuleImport2\build.gradle">Open File</a>

    I followed these guides: https://stackoverflow.com/questions/41764338/importing-module-in-android-studio and https://github.com/MagicMicky/FreemiumLibrary/wiki/Import-the-library-in-Android-Studio

    Do you have a recommended method to adding your library to an existing project and be able to modify files?

    opened by Therefore 7
  • OutOfMemoryError createBitmap

    OutOfMemoryError createBitmap

    Hi Alex Melnykov, Firstly I really thank you for your library. I solved my problems about rendering more than 100k markers. But now I'm facing out of memory error about bitmap when I leave and came back to map fragment. I think bitmap resources may not be cleared when fragment was destroyed at first time. Because the first time the map and its clustering is working fine. Do you have any suggestion to solve this problem? I'm new for map implementing, feel free to advise me. Thanks, Gaw

    help wanted 
    opened by Gawvie 4
  • Animate cluster when visible

    Animate cluster when visible

    Great library, right now I was looking for a solution whith clustering...

    I see in the demo/gir that the cluster is hidden and shown only when necessary

    Is posible add animate fade-in when cluster is needed draw in viewport? Similar objects in google maps, labels, icons...

    Or other feature, posible set factor viewport "visible" increase the viewport as if it were 1.2f, so the clusters are pre-loaded before being visualized

    enhancement good first issue 
    opened by webserveis 4
  • Make ClusterRenderer exchangable

    Make ClusterRenderer exchangable

    In my sideproject I wanted to exchange the renderer to change how tag's are set and the animation. So I thought sharing this is a good idea.

    Another way of archiving this would be by defaulting to the ClusterRenderer and having a setter that makes it possible to exchange it later on.

    You are more then welcome to give some thoughts on that.

    enhancement 
    opened by meierjan 3
  • synchronization of mQuadTree

    synchronization of mQuadTree

    Do I understand your code correctly the synchronization of mQuadTree is based on the fact that mExecutor is single-threaded?

    Opening issues is the only option I can think of to ask questions so I hope u don't bother.

    opened by meierjan 3
  • No way to programatically display infoWindow for ClusterItem

    No way to programatically display infoWindow for ClusterItem

    Can't find a way to get hold of the ClusterItem to then be able to programatically show infoWindow. Is there a way to do this that I've missed? If not I'll work on a pull request as I think it would be really useful.

    Thanks

    opened by PJHaynes304 2
  • Issue in clusters calculation depending on the location

    Issue in clusters calculation depending on the location

    Hi !

    I'm from Argentina and saw that with negatives values for latitude and longitude the method getClusters return 0.

    I fixed it replacing in ClusterManager.java Line: 176 the next sentence:

             `   List<T> points = mQuadTree.queryRange(north > south ? north : south, west < east ? west : east, south < north ? south : north, east > west ? east : west);`
    

    I not have much time now to test whether is the ideal and global solution for the whole map, but it can be a good starting point.

    Regards!

    opened by cuentasbesmartmobile 2
  • Handling 180/-180 overlap

    Handling 180/-180 overlap

    Hi! We've found out that you ClusterManager removes all the markers from the map when camera bounds include 180'th meridian, coz this situation is not properly handled. You can reproduce it by adding points around 180/-180 to your MapActivity::onMapReady

            clusterItems.add(new SampleClusterItem(new LatLng(1, 179)));
            clusterItems.add(new SampleClusterItem(new LatLng(2, -179)));
    

    I've added naive WO.

    bug 
    opened by horse315 2
  • Markers not removing after being drawn on map

    Markers not removing after being drawn on map

    Hello, I have an issue where i have 3 types of markers store in 3 list and i display them one at a time by calling clusterManager.setItems(list) It works very well but some of the markers once they have been drawn on the map (i.e not in a cluster anymore) are not removed when i change the cluster array. Here is a video showing some markers (blue) being removed when in a cluster but not anymore when they have been drawn on the map.

    Video showing the bug

    And here the code how i switch between the lists :

    clusterManager.setItems(new ArrayList<>());
    clusterManager.onCameraIdle();
    clusterManager.setItems(newList);
    

    If i remove the call to onCameraIdle more markers stay on the map. I have more than 10 000 markers.

    Since your library hasn't been updated since 2 years i have search for alternative but haven't found any as good as yours for clustering thousands of markers.

    opened by Seeyko 1
  • Release to mavenCentral

    Release to mavenCentral

    JCenter is shutting down: https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/

    Since JCenter is shutting down, please consider publishing your SDK to Maven Central

    Thanks.

    opened by ensarbayhan 2
  • How can I migrate your library from gms to androdi libraries maps?

    How can I migrate your library from gms to androdi libraries maps?

    Hello. In my app when I click a cluster it opens dialog fragment with list of items. Then when I click item it opens another fragment. And when I pop back to map fragment my map very lagging. Then if I open dialog again and dismiss it map works as usual. Found same problem here but there is no any solutions that help me. It seems that the problem with gms maps, so I tried to modify your library in my app using 'com.google.android.libraries.maps:maps:3.1.0-beta' instead gms and it solved problem with dialog but there is another problem that some markers don't remove when clustering. Can you help me migrate your library using android libraries maps instead gms?

    opened by stenol53 0
  • custom cluster marker

    custom cluster marker

    Good morning. Thank you for creating a useful library first. I'm currently using custom cluster markers. When the map is zoomed in or out, the cluster markers change to existing markers. How can I deal with it so that it doesn't change?

    Because it is a Google translation, it may not be translated correctly @makovkastar

    opened by lomo57 0
  • Crashes when minify/proguard/r8 is enabled

    Crashes when minify/proguard/r8 is enabled

    By using the ObjectAnimator when animating map markers, the variable name position gets obfuscated for release, crashing the app.

        private void animateMarkerToLocation(@NonNull final Marker marker, @NonNull LatLng targetLocation,
                                             final boolean removeAfter) {
            ObjectAnimator objectAnimator = ObjectAnimator.ofObject(marker, "position",
                    new LatLngTypeEvaluator(), targetLocation);
            objectAnimator.setInterpolator(new FastOutSlowInInterpolator());
    

    I don't know if just adding to the README is enough, or maybe preventing this by embedding proguard rules in the project.

    -keep class com.google.android.gms.maps.model.Marker { *; }
    
    opened by vitorhugods 0
Owner
Sharewire
Sharewire
FilePicker is a small and fast file selector library that is constantly evolving with the goal of rapid integration, high customization, and configurability~

Android File Picker ??️ 中文简体 Well, it doesn't have a name like Rocky, Cosmos or Fish. Android File Picker, like its name, is a local file selector fra

null 786 Jan 6, 2023
AndroidPhotoFilters aims to provide fast, powerful and flexible image processing instrument for creating awesome effects on any image media.

PhotoFiltersSDK PhotoFiltersSDK aims to provide fast, powerful and flexible image processing instrument for creating awesome effects on any image medi

Zomato 2.5k Dec 23, 2022
Postman is a reactive One-tap SMS verification library. This library allows the usage of RxJava with The SMS User Consent API

What is Postman? Postman is a reactive One-tap SMS verification library. This library allows the usage of RxJava with The SMS User Consent API Usage P

Cafer Mert Ceyhan 129 Dec 24, 2022
Material Design text field that comes in a box, based on (OLD) Google Material Design guidelines.

TextFieldBoxes A new Material Design text field that comes in a box, based on Google Material Design guidelines. ???? 中文看这里 UPDATE NOTICE 1.4.5 Releas

Mark Wang 769 Jan 7, 2023
Navigation pattern like in Google News Stand app with transitions

Google-NewsStand-Animation-Android Navigation pattern like in Google News Stand app with transitions Getting Started In your build.gradle dependencies

Hariprasanth S 129 Nov 11, 2022
[] Android library for using the Honeycomb animation API on all versions of the platform back to 1.0!

DEPRECATED NineOldAndroids is deprecated. No new development will be taking place. Existing versions will (of course) continue to function. New applic

Jake Wharton 4.5k Jan 9, 2023
Implementation of Ripple effect from Material Design for Android API 9+

RippleEffect ExpandableLayout provides an easy way to create a view called header with an expandable view. Both view are external layout to allow a ma

Robin Chutaux 4.9k Dec 30, 2022
A backport of the new Transitions API for Android

TransitionsBackport Android library for using the Transitions API released with Android KitKat on older versions of Android. At the moment, it is comp

Stéphane Guérin 578 Dec 29, 2022
Circle based animations for Android (min. API 11)

CircularTools Circle based animations for Android (min. API 11) Currently implemented: Circular reveal Circular transform Radial reaction Reveal:YouTu

AutSoft 209 Jul 20, 2022
Splash screen demo that used with ‘Splash Screen‘ API on Android 12.

Splash Screen Feature Splash screen demo that used with Splash Screen API on Android 12. ?? Screenshot Default splash screen Splash screen with animat

Ellison Chan 60 Nov 16, 2022
Android StackBlur is a library that can perform a blurry effect on a Bitmap based on a gradient or radius, and return the result. The library is based on the code of Mario Klingemann.

Android StackBlur Android StackBlur is a library that can perform a blurry effect on a Bitmap based on a gradient or radius, and return the result. Th

Enrique López Mañas 3.6k Dec 29, 2022
Android Country Picker is a Kotlin-first, flexible and powerful Android library that allows to integrate Country Picker with just a few lines.

1. Add dependency dependencies { implementation 'com.hbb20:android-country-picker:X.Y.Z' } For latest version, 2. Decide your use-case

Harsh B. Bhakta 65 Dec 6, 2022
Android library for swipable gestures

Swipper Android Library for custom views to control brightness , volume and seek through swipable gestures . These views could easily replace the conv

Mobile Development Group 105 Dec 30, 2022
Android Library that lights items for tutorials or walk-throughs etc...

Spotlight Gradle dependencies { implementation 'com.github.takusemba:spotlight:x.x.x' } Usage val spotlight = Spotlight.Builder(this) .setTarg

TakuSemba 3.4k Jan 4, 2023
[] An Android library which allows developers to easily add animations to ListView items

DEPRECATED ListViewAnimations is deprecated in favor of new RecyclerView solutions. No new development will be taking place, but the existing versions

Niek Haarman 5.6k Dec 30, 2022
Android Rubber Picker Library

RubberPicker RubberPicker library contains the RubberSeekBar and RubberRangePicker, inspired by Cuberto's rubber-range-picker. Getting started Setting

Chrisvin Jem 547 Jan 5, 2023
EtsyBlur is an Android library that allows developers to easily add a glass-like blur effect implemented in the Etsy app.

EtsyBlur EtsyBlur is an Android library that allows developers to easily add a glass-like blur effect implemented in the past Etsy app. Try out the sa

Manabu S. 755 Dec 29, 2022
Android library. Flexible components for chat UI implementation with flexible possibilities for styling, customizing and data management. Made by Stfalcon

ChatKit for Android ChatKit is a library designed to simplify the development of UI for such a trivial task as chat. It has flexible possibilities for

Stfalcon LLC 3.6k Jan 5, 2023
An Android library which provides simple Item animations to RecyclerView items

RecyclerViewItemAnimators Library Travis master: This repo provides: Appearance animations Simple animators for the item views Quick start You can now

Gabriele Mariotti 3.1k Dec 16, 2022