Introduction: Google map is a great way to show the user current location in the world and some time we need to show more than one image at a location. The cluster is nothing more than a group of markers combined together.
To achieve it in Android google provide us dependencies that we have to add in the application grade file.compile 'com.google.android.gms:play-services-maps:9.0.2'compile 'com.google.maps.android:android-maps-utils:0.4.3'
Here, i'm going to explain a clustering utility that i have used in one of my projects. So, for use it you have to provide an instance of google map and screen context in the constructor of utility and call init() method for initial setup. And call addUser() method with locations of the item.
import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.widget.TextView;import com.crashlytics.android.Crashlytics;import com.google.android.gms.maps.CameraUpdateFactory;import com.google.android.gms.maps.GoogleMap;import com.google.android.gms.maps.model.BitmapDescriptor;import com.google.android.gms.maps.model.BitmapDescriptorFactory;import com.google.android.gms.maps.model.LatLng;import com.google.android.gms.maps.model.LatLngBounds;import com.google.android.gms.maps.model.MarkerOptions;import com.google.maps.android.clustering.Cluster;import com.google.maps.android.clustering.ClusterItem;import com.google.maps.android.clustering.ClusterManager;import com.google.maps.android.clustering.view.DefaultClusterRenderer;import com.google.maps.android.ui.IconGenerator;import java.util.List;public class GoogleMapClusterUtil implements ClusterManager.OnClusterClickListener <GoogleMapClusterUtil.Person>, ClusterManager.OnClusterInfoWindowClickListener<GoogleMapClusterUtil.Person>, ClusterManager.OnClusterItemClickListener<GoogleMapClusterUtil.Person>, ClusterManager.OnClusterItemInfoWindowClickListener<GoogleMapClusterUtil.Person> {private final Context mContext;private final GoogleMap mGoogleMap;private ClusterManager<Person> mClusterManager;public GoogleMapClusterUtil(Context context, GoogleMap googleMap) {mContext = context;mGoogleMap = googleMap;}/*** Create instance of cluster.*/public void init() {mClusterManager = new ClusterManager<>(mContext, mGoogleMap);mClusterManager.setRenderer(new PersonRenderer());mGoogleMap.setOnMarkerClickListener(mClusterManager);mGoogleMap.setOnInfoWindowClickListener(mClusterManager);mClusterManager.setOnClusterClickListener(this);mClusterManager.setOnClusterInfoWindowClickListener(this);mClusterManager.setOnClusterItemClickListener(this);mClusterManager.setOnClusterItemInfoWindowClickListener(this);mClusterManager.cluster();
}/*** Update cluster on camera idle.*/public void onCameraIdle() {mClusterManager.onCameraIdle();}public void addUser(List<Location> userNearMe) {clearAllItem();for (Location appUserLocation : userNearMe) {// the address is blank for now, will be used latermClusterManager.addItem(new Person(new LatLng(appUserLocation.getLatitude(), appUserLocation.getLongitude()), 0));}}/*** Delete all cluster from map.*/public void clearAllItem() {mClusterManager.clearItems();}@Overridepublic boolean onClusterClick(Cluster<Person> cluster) {// Zoom in the cluster. Need to create LatLngBounds and including all the cluster items// inside of bounds, then animate to center of the bounds.// Create the builder to collect all essential cluster items for the bounds.LatLngBounds.Builder builder = LatLngBounds.builder();for (ClusterItem item : cluster.getItems()) {builder.include(item.getPosition());}// Get the LatLngBoundsfinal LatLngBounds bounds = builder.build();// Animate camera to the boundstry {mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100));} catch (Exception e) {Crashlytics.logException(e);}return true;}@Overridepublic void onClusterInfoWindowClick(Cluster<Person> cluster) {// onClusterInfoWindowClick}@Overridepublic boolean onClusterItemClick(Person person) {return false;}@Overridepublic void onClusterItemInfoWindowClick(Person person) {// onClusterItemInfoWindowClick}public class Person implements ClusterItem {public final int id;private final LatLng mPosition;private Person(LatLng position, int id) {this.id = id;mPosition = position;}public int getId() {return id;}@Overridepublic LatLng getPosition() {return mPosition;}@Overridepublic String getTitle() {return null;}@Overridepublic String getSnippet() {return null;}}/*** Manage cluster update.*/private class PersonRenderer extends DefaultClusterRenderer<Person> {private PersonRenderer() {super(mContext, mGoogleMap, mClusterManager);}@Overrideprotected void onBeforeClusterItemRendered(Person person, MarkerOptions markerOptions) {// Draw a single person.// Set the info window to show their name.if (person.getId()>0){markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.location_package));}else{markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.location));}}@Overrideprotected void onBeforeClusterRendered(Cluster<Person> cluster, MarkerOptions markerOptions) {// Draw multiple people.// Note: this method runs on the UI thread. Don't spend too much time in here (like in this example).IconGenerator iconGenerator = new IconGenerator(mContext);iconGenerator.setBackground(null);LayoutInflater myInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);View activityView = myInflater.inflate(R.layout.item_cluster, null, false);activityView.findViewById(R.id.item_cluster_iv_cluster_icon).setBackgroundResource(R.drawable.location_blank);if (cluster.getSize() > 99) {((TextView) activityView.findViewById(R.id.amu_text)).setText(String.valueOf("99+"));} else {((TextView) activityView.findViewById(R.id.amu_text)).setText(String.valueOf(cluster.getSize()));}iconGenerator.setContentView(activityView);BitmapDescriptor icon = BitmapDescriptorFactory.fromBitmap(iconGenerator.makeIcon());markerOptions.icon(icon);}@Overrideprotected boolean shouldRenderAsCluster(Cluster cluster) {// Always render clusters.return cluster.getSize() > 1;}}}
for display cluster google map i have used following XML file. You can change it according to your requirement.
layout: item_cluster
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="30dp"android:layout_height="30dp"android:padding="2dp"><ImageViewandroid:id="@+id/item_cluster_iv_cluster_icon"android:layout_width="match_parent"android:layout_height="match_parent"android:contentDescription="@null"/><TextViewandroid:id="@+id/amu_text"android:layout_width="wrap_parent"android:layout_height="wrap_parent"android:layout_gravity="center"android:gravity="center"android:paddingBottom="2dp"/></FrameLayout>
At the end build it in your project. You will see, after double click on the map. it will expand item.