MauriF MauriF - 1 month ago 20
Android Question

How to use Viewport Marker Management on Android

I haven't found any complete explanation on how to use this technique on Android so I decided to create a Q&A thread.

If your app has to show a large amount of markers on a google map and clustering them is not enough to prevent your app from working too slow, then one of your best choices is to use this Viewport Marker Management technique. You can read the theoretical explanation here: https://developers.google.com/maps/articles/toomanymarkers

I wrote a short guide below...

Answer

1°--- In the activity where map is created you have to set the OnCameraChangeListener and get the bounds of your screen like this:

mMap.setOnCameraChangeListener(new OnCameraChangeListener() {

        @Override
        public void onCameraChange(CameraPosition arg0) {

        LatLngBounds bounds = mapa.getProjection().getVisibleRegion().latLngBounds;

        }

2°--- This step may vary depending how you fetch the markers data. Basically, what you have to do is to calculate if the lat and long of each of your markers are inside the screen bounds. I will show you how to do it by fetching the data from a SQLite data base storing latitud and longitude in two different DOUBLE clomuns inside the markers table.

mMap.setOnCameraChangeListener(new OnCameraChangeListener() {

        @Override
        public void onCameraChange(CameraPosition arg0) {

        LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;

        LatLng northeast = bounds.northeast;
        String boundLat = String.valueOf(northeast.latitude);
        String boundLong = String.valueOf(northeast.longitude);

        LatLng southwest = bounds.southwest;

        String boundLat2 = String.valueOf(southwest.latitude);
        String boundLong2 = String.valueOf(southwest.longitude);

        //Remove all markers from map

        mMap.clear(); // or if your a using cluster manager:
        //mClusterManager.clearItems();

        String[] fields = new String[] { "name", "latitude", "longitude" };
        String[] args = new String[] {boundLat, boundLong, boundLat2, boundLong2,};

        Cursor markers = dataBase.query("markers", fields, "latitude<=? AND longitude<=? AND latitude>=? AND longitude>=?");

        if (markers.moveToFirst()) {
                do {
                    mMap.addMarker(new MarkerOptions()
                    .position(new LatLng(marker.getDouble(1), marker.getDouble(2)))
                    .title(marker.getString(0)) );

                     // or if you are using cluster manager create and add the items as you normaly do.

                   } while (c.moveToNext());

                   //if using cluster manager add :
                   //mClusterManager.cluster();
                   }
    }
});

The idea is pretty easy, just have in mind that your markers lat and longi have to be smaller than the northeast position of your screen and bigger than the southwest corner, or just use the LatLngBounds.contains function.

EDITED:

To avoid InfoWindow getting closed when clicking on a marker which is not already in the center of the screen, you can change the marker click listener default action, removing the camera move.

map.setOnMarkerClickListener(new OnMarkerClickListener() {

        @Override
        public boolean onMarkerClick(Marker arg0) {
            arg0.showInfoWindow();

            return true; //must be true, if not, it will execute the default code after yours
        }

    });
Comments