ANDROID GOOGLE MAPs Marker - Custom MARKER CLUSTERING

ANDROID GOOGLE MAPs MARKER CLUSTERING

In this post we are going to learn about use of google maps marker clustering when we requires to show a large number of data points on the Google map.

For this we are using the google maps marker Clustering Utility class.

google maps marker cluster default image

 

in the above image The number on a cluster indicates how many markers it contains. Once we zoom onto cluster location we’ll able see the markers. We can also show Current Location with Zoom Options

Let's get Started

Step 1: Create Android application

Step 2: Setup Google Maps API to application.

Check the link to Setup Google Maps API

Step 3: Add dependencies to gradle file

implementation 'com.google.maps.android:android-maps-utils:1.0.2'
implementation 'com.google.android.gms:play-services-maps:17.0.0'

Step 4:

Now need to do marker clustering done on Google Maps. The simplest way to show the cluster, first, we need to implement ClusterItem on our model class. Let’s create a simple User class that implements ClusterItem.

package com.rrtutors.googlemapcluster

import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.clustering.ClusterItem

class User constructor(username: String,latLng: LatLng,url :String): ClusterItem {

    var username=username;
    var url=url;
    var latLng=latLng;
    override fun getSnippet(): String {

        return "";
    }

    override fun getTitle(): String {

        return username;
    }

    override fun getPosition(): LatLng {
        return latLng;

    }


}
  • The ClusterItem returns the position of the marker, which later Google Maps use’s and show the marker. Must always return same LatLng position.
  • Title of the marker which will be visible when you click on a single marker.

Step 5: Update MainActivity

package com.rrtutors.googlemapcluster

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.SupportMapFragment
import com.google.maps.android.clustering.ClusterManager
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.LatLng
import java.util.*


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val supportMapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?  // 1
        supportMapFragment!!.getMapAsync { googleMap ->
            // 2
            setUpClusterManager(googleMap)
        }


    }

    private fun setUpClusterManager(googleMap: GoogleMap) {
        val clusterManager = ClusterManager<User>(applicationContext , googleMap)  // 3
        googleMap.setOnCameraIdleListener(clusterManager)
        val items = getItems()

        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(items?.toList()?.get(6)?.latLng, 14.0f));
        clusterManager.addItems(items)  // 4
        clusterManager.cluster()  // 5
    }

    private fun getItems(): MutableCollection<User>? {
        return Arrays.asList(
            User("Location1", LatLng(-31.563910, 147.154312), "https://www.rrtutors.com"),
            User("Location2", LatLng(-33.718234, 150.363181), "https://www.rrtutors.com"),
            User("Location3", LatLng(-33.727111, 150.371124), "https://www.rrtutors.com"),
            User("Location4", LatLng(-33.848588, 151.209834), "https://www.rrtutors.com"),
            User("Location5", LatLng(-33.851702, 151.216968), "https://www.rrtutors.com"),
            User("Location6", LatLng(-34.671264, 150.863657), "https://www.rrtutors.com"),
            User("Location7", LatLng(-35.304724, 148.662905), "https://www.rrtutors.com"),
            User("Location8", LatLng(-36.817685, 175.699196), "https://www.rrtutors.com"),
            User("Location9", LatLng(-36.828611, 175.790222), "https://www.rrtutors.com"),
            User("Location10", LatLng(-37.750000, 145.116667), "https://www.rrtutors.com"),
            User("Location11", LatLng(-37.759859, 145.128708), "https://www.rrtutors.com"),
            User("Location12", LatLng(-37.765015, 145.133858), "https://www.rrtutors.com"),
            User("Location13", LatLng(-37.770104, 145.143299), "https://www.rrtutors.com"),
            User("Location14", LatLng(-37.773700, 145.145187), "https://www.rrtutors.com"),
            User("Location15", LatLng(-37.774785, 145.137978), "https://www.rrtutors.com"),
            User("Location16", LatLng(-37.819616, 144.968119), "https://www.rrtutors.com"),
            User("Location17", LatLng(-38.330766, 144.695692), "https://www.rrtutors.com"),
            User("Location18", LatLng(-39.927193, 175.053218), "https://www.rrtutors.com"),
            User("Location19", LatLng(-41.330162, 174.865694), "https://www.rrtutors.com"),
            User("Location20", LatLng(-42.734358, 147.439506), "https://www.rrtutors.com"),
            User("Location21", LatLng(-42.734358, 147.501315), "https://www.rrtutors.com"),
            User("Location22", LatLng(-42.735258, 147.438000), "https://www.rrtutors.com"),
            User("Location23", LatLng(-43.999792, 170.463352), "https://www.rrtutors.com")
        )
    }
}

Explanation for above code

  • Obtain the SupportMapFragment from xml.
  • Registering a callback to get notified when we’re ready to use Google Maps.
  • Creates a new ClusterManager which later handles the clustering for our markers. Note the type of argument<User> which declares the ClusterManager to be of User type.
  • Feed the items to our newly created ClusterManager.
  • Call the cluster method, you may want to call this method after feeding items to ClusterManager.

That's it, it will show the Markers with clustering when ZoomOut the marker.

Custom Icon inside Marker

Now let’s say we need to change the default marker icon which shows inside the Cluster Marker with custom marker. For that, we need to create a new ClusterRenderer with to extend the DefaultClusterRenderer class.

package com.rrtutors.googlemapcluster

import android.content.Context
import android.graphics.Bitmap
import android.widget.ImageView
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.BitmapDescriptorFactory
import com.google.android.gms.maps.model.MarkerOptions
import com.google.maps.android.clustering.ClusterManager
import com.google.maps.android.clustering.view.DefaultClusterRenderer
import com.google.maps.android.ui.IconGenerator
import android.view.ViewGroup

class MarkerClusterRenderer(context:Context, map:GoogleMap, clusterManager:ClusterManager<User>?):
    DefaultClusterRenderer<User>(context, map, clusterManager) {
    private val MARKER_DIMENSION = 48  // 2
    private var iconGenerator: IconGenerator? = null
    private var markerImageView: ImageView? = null
    init {
        iconGenerator = IconGenerator(context)  // 3
        markerImageView = ImageView(context)
        markerImageView!!.setLayoutParams(ViewGroup.LayoutParams(MARKER_DIMENSION, MARKER_DIMENSION))
        markerImageView!!.setBackgroundColor(getColor(R.color.colorPrimary))
        iconGenerator!!.setContentView(markerImageView)
    }

    override fun onBeforeClusterItemRendered(item: User?, markerOptions: MarkerOptions?) {
        super.onBeforeClusterItemRendered(item, markerOptions)

        markerImageView?.setImageResource(R.drawable.img_chef);  // 6
       var icon = iconGenerator?.makeIcon();  // 7
        markerOptions?.icon(BitmapDescriptorFactory.fromBitmap(icon));  // 8
        markerOptions?.title(item?.getTitle());
    }


}

 

In the above code we added Marker options to set google maps marker icon and google maps marker title

Now call this MarkerClusterRenderer after creating the object of 

val clusterManager = ClusterManager<User>(applicationContext , googleMap)

private fun setUpClusterManager(googleMap: GoogleMap) {
    val clusterManager = ClusterManager<User>(applicationContext , googleMap)  // 3
    clusterManager.renderer = MarkerClusterRenderer(this, googleMap, clusterManager)

    googleMap.setOnCameraIdleListener(clusterManager)
    val items = getItems()

    googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(items?.toList()?.get(6)?.latLng, 14.0f));
    clusterManager.addItems(items)  // 4
    clusterManager.cluster()  // 5
}

 

The output will become like below

Googlemaps Custome Marker Clustering