Android Maps Utils : Markers in the same location

Recently, I came across with a request in the library Android Maps Utils which requested a fix for a problem when the markers have exact the same location. As this is a library I used recently and I was reading the code when I was integrating in an Android App, I just decided to implement the feature and here you can find the experience. All the details regarding the changes can be found in this pull request.

In case you want to include this functionality in your app, until the pull request is not accepted you would need to generate the library file including the pull request and then include it in your project through Gradle. After that, you can include to your map as shown in the code below:

mClusterManager = new ClusterManager<>(this, getMap()); 
getMap().setOnMarkerClickListener(mClusterManager);
getMap().setOnCameraMoveListener(mClusterManager);

mClusterManager.cluster();

The default implementation will distribute the markers with the same location around the real lat/long value following a circle when the user tap on the marker containing all the markers in the same location. To distribute the markers, the zoom level shown has to be the maximum zoom level, and once the user makes a zoom out all the markers distributed will be relocated to the original cluster.

Of course, this could be implemented in many ways and with different approaches, this is just an example of a way to get the feature implemented, I just wanted to get fun implementing and sharing with the world. It is important to mention a change needed in the ClusterItem interface could produce a backward compatibility problem as a copy has been added.

/**  * Produces a copy of the same object but setting the given location.
 *
 * @return The new object copied.
 */
ClusterItem copy(double lat, double lng);
As you can see in the first code block, cluster manager needs to be set up to listen camera moves actions on the map, if you also need to listen to the same events in your app or code just do as the code below:

mMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
        @Override
        public void onCameraMove() {
            mClusterManager.onCameraMove(); 
            // your onCameraMove code
        }
});
 You can place your code also before call mClusterManager.onCameraMove(); or even call mClusterManager.onCameraMove(); only when you need to distribute the markers of the cluster, it will depend in your app needs.

As mentioned, the default distributor for a cluster with all the markers in the same location distributes them in a circle, and it can be replaced just calling to mClusterManager setClusterItemsDistributor(mYourDistributorImplementation);. In case you need to implement your own distributor you need to implement the interface ClusterItemDistributor.

/**  * It distributes the items in a cluster.
 */
public interface ClusterItemsDistributor {

    /**
     * Proceed with the distribution of the items in a cluster.
     */
    void distribute(Cluster cluster);

    /**
     * Proceed to collect the items back to their previous state.
     */
    void collect();
}
Just take into account distribute(Cluster cluster); needs to distribute all the items in the cluster and collect(); needs to get the markers to their original state and cluster, see DefaultClusterItemsDistributor as an example.

Please, if you use this feature or you implement your own distributor let me know, or if you have any feedback or question I will be more than happy to listen and improve what I've done, helping others and getting help from others is the way to learn something new every day.

0 comentarios: