Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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...

like image 724
MauriF Avatar asked Sep 25 '14 19:09

MauriF


People also ask

How do I add a marker to Google Maps Android?

For adding a custom marker to Google Maps navigate to the app > res > drawable > Right-Click on it > New > Vector Assets and select the icon which we have to show on your Map. You can change the color according to our requirements. After creating this icon now we will move towards adding this marker to our Map.


1 Answers

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
        }

    });
like image 102
MauriF Avatar answered Oct 03 '22 04:10

MauriF