[android] Android map v2 zoom to show all the markers

I have 10 markers in the GoogleMap. I want to zoom in as much as possible and keep all markers in view? In the earlier version this can be achieved from zoomToSpan() but in v2 I have no idea how about doing that. Further, I know the radius of the circle that needs to be visible.

The answer is


I had similar problem, using following code solved the issue:

CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 5) generally the location differences in my case are no more than two neighbour cities.

zoom to fit all markers on map google maps v2


I worked the same problem for showing multiple markers in Kotlin using a fragment

first declare a list of markers

private lateinit var markers: MutableList<Marker>

initialize this in the oncreate method of the frament

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
                         ): View? {
    //initialize markers list

    markers = mutableListOf()
   
    return inflater.inflate(R.layout.fragment_driver_map, container, false)
}

on the OnMapReadyCallback add the markers to the markers list

private val callback = OnMapReadyCallback { googleMap ->

    map = googleMap

    markers.add(
        map.addMarker(
            MarkerOptions().position(riderLatLng)
                .title("Driver")
                .snippet("Driver")
                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED))))


    markers.add(
        map.addMarker(
            MarkerOptions().position(driverLatLng)
                .title("Driver")
                .snippet("Driver")
                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))))

Still on the callback

//create builder
    val builder = LatLngBounds.builder()

    //loop through the markers list
    for (marker in markers) {

        builder.include(marker.position)
    }
    //create a bound
    val bounds = builder.build()

    //set a 200 pixels padding from the edge of the screen
    val cu = CameraUpdateFactory.newLatLngBounds(bounds,200)
    
    //move and animate the camera
    map.moveCamera(cu)
    //animate camera by providing zoom and duration args, callBack set to null
    map.animateCamera(CameraUpdateFactory.zoomTo(10f), 2000, null)

Merry coding guys


Use the method "getCenterCoordinate" to obtain the center coordinate and use in CameraPosition.

private void setUpMap() {
    mMap.setMyLocationEnabled(true);
    mMap.getUiSettings().setScrollGesturesEnabled(true);
    mMap.getUiSettings().setTiltGesturesEnabled(true);
    mMap.getUiSettings().setRotateGesturesEnabled(true);

    clientMarker = mMap.addMarker(new MarkerOptions()
            .position(new LatLng(Double.valueOf(-12.1024174), Double.valueOf(-77.0262274)))
            .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_taxi))
    );
    clientMarker = mMap.addMarker(new MarkerOptions()
            .position(new LatLng(Double.valueOf(-12.1024637), Double.valueOf(-77.0242617)))
            .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_location))
    );

    camPos = new CameraPosition.Builder()
            .target(getCenterCoordinate())
            .zoom(17)
            .build();
    camUpd3 = CameraUpdateFactory.newCameraPosition(camPos);
    mMap.animateCamera(camUpd3);
}


public LatLng getCenterCoordinate(){
    LatLngBounds.Builder builder = new LatLngBounds.Builder();
    builder.include(new LatLng(Double.valueOf(-12.1024174), Double.valueOf(-77.0262274)));
    builder.include(new LatLng(Double.valueOf(-12.1024637), Double.valueOf(-77.0242617)));
    LatLngBounds bounds = builder.build();
    return bounds.getCenter();
}

Google Map V2

The following solution works for Android Marshmallow 6 (API 23, API 24, API 25, API 26, API 27, API 28). It also works in Xamarin.

LatLngBounds.Builder builder = new LatLngBounds.Builder();

//the include method will calculate the min and max bound.
builder.include(marker1.getPosition());
builder.include(marker2.getPosition());
builder.include(marker3.getPosition());
builder.include(marker4.getPosition());

LatLngBounds bounds = builder.build();

int width = getResources().getDisplayMetrics().widthPixels;
int height = getResources().getDisplayMetrics().heightPixels;
int padding = (int) (width * 0.10); // offset from edges of the map 10% of screen

CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, width, height, padding);

mMap.animateCamera(cu);

I have one other way to do this same thing works perfectly. so the idea behind to show all markers on the screen we need a center lat long and zoom level. here is the function which will give you both and need all marker's Latlng objects as input.

 public Pair<LatLng, Integer> getCenterWithZoomLevel(LatLng... l) {
    float max = 0;

    if (l == null || l.length == 0) {
        return null;
    }
    LatLngBounds.Builder b = new LatLngBounds.Builder();
    for (int count = 0; count < l.length; count++) {
        if (l[count] == null) {
            continue;
        }
        b.include(l[count]);
    }

    LatLng center = b.build().getCenter();

    float distance = 0;
    for (int count = 0; count < l.length; count++) {
        if (l[count] == null) {
            continue;
        }
        distance = distance(center, l[count]);
        if (distance > max) {
            max = distance;
        }
    }

    double scale = max / 1000;
    int zoom = ((int) (16 - Math.log(scale) / Math.log(2)));
    return new Pair<LatLng, Integer>(center, zoom);
}

This function return Pair object which you can use like

Pair pair = getCenterWithZoomLevel(l1,l2,l3..); mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(pair.first, pair.second));

you can instead of using padding to keep away your markers from screen boundaries, you can adjust zoom by -1.


Working fine for me.

From this code, I am displaying multiple markers with particular zoom on map screen.

// Declared variables

private LatLngBounds bounds;
private LatLngBounds.Builder builder;

// Method for adding multiple marker points with drawable icon

private void drawMarker(LatLng point, String text) {

        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(point).title(text).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon));
        mMap.addMarker(markerOptions);
        builder.include(markerOptions.getPosition());

    }

// For adding multiple markers visible on map

@Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        builder = new LatLngBounds.Builder();
    for (int i = 0; i < locationList.size(); i++) {

        drawMarker(new LatLng(Double.parseDouble(locationList.get(i).getLatitude()), Double.parseDouble(locationList.get(i).getLongitude())), locationList.get(i).getNo());

     }
     bounds = builder.build();
     CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
     mMap.animateCamera(cu);

Note - This is not a solution to the original question. This is a solution to one of the subproblems discussed above.

Solution to @andr Clarification 2 -

Its really problematic when there's only one marker in the bounds and due to it the zoom level is set to a very high level (level 21). And Google does not provide any way to set the max zoom level at this point. This can also happen when there are more than 1 marker but they are all pretty close to each other. Then also the same problem will occur.

Solution - Suppose you want your Map to never go beyond 16 zoom level. Then after doing -

CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
mMap.moveCamera(cu);

Check if your zoom level has crossed level 16(or whatever you want) -

float currentZoom = mMap.getCameraPosition().zoom;

And if this level is greater than 16, which it will only be if there are very less markers or all the markers are very close to each other, then simply zoom out your map at that particular position only by seting the zoom level to 16.

mMap.moveCamera(CameraUpdateFactory.zoomTo(16));

This way you'll never have the problem of "bizarre" zoom level explained very well by @andr too.


I couldnt use the onGlobalLayoutlistener, so here is another solution to prevent the "Map size can't be 0. Most likely, layout has not yet occured for the map view. Either wait until layout has occurred or use newLatLngBounds(LatLngBounds, int, int, int) which allows you to specify the map's dimensions." error:

mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { 
@Override 
public void onMapLoaded() { 
    mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 15));
 } 
});

this would help.. from google apis demos

private List<Marker> markerList = new ArrayList<>();
Marker marker = mGoogleMap.addMarker(new MarkerOptions().position(geoLatLng)
                .title(title));
markerList.add(marker);
    // Pan to see all markers in view.
    // Cannot zoom to bounds until the map has a size.
    final View mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView();
    if (mapView!=null) {
        if (mapView.getViewTreeObserver().isAlive()) {
            mapView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @SuppressWarnings("deprecation") // We use the new method when supported
                @SuppressLint("NewApi") // We check which build version we are using.
                @Override
                public void onGlobalLayout() {
                    //Calculate the markers to get their position
                    LatLngBounds.Builder b = new LatLngBounds.Builder();
                    for (Marker m : markerList) {
                        b.include(m.getPosition());
                    }
                    // also include current location to include in the view
                    b.include(new LatLng(mLocation.getLatitude(),mLocation.getLongitude()));

                    LatLngBounds bounds = b.build();
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                        mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    } else {
                        mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    }
                    mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
                }
            });
        }
    }

for clear info look at this url. https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java


   //For adding a marker in Google map
        MarkerOptions mp = new MarkerOptions();
        mp.position(new LatLng(Double.parseDouble(latitude), Double.parseDouble(longitude)));
        mp.snippet(strAddress);
        map.addMarker(mp);

        try {

            b = new LatLngBounds.Builder();

            if (MapDetailsList.list != null && MapDetailsList.list.size() > 0) {

                for (int i = 0; i < MapDetailsList.list.size(); i++) {

                    b.include(new LatLng(Double.parseDouble(MapDetailsList.list.get(i).getLatitude()),
                            Double.parseDouble(MapDetailsList.list.get(i).getLongitude())));

                }
                LatLngBounds bounds = b.build();

                DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
                int width = displayMetrics.widthPixels;
                int height = displayMetrics.heightPixels;

                // Change the padding as per needed
                CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, width-200, height-200, 5);
                // map.setCenter(bounds.getCenter());

                map.animateCamera(cu);

            }

        } catch (Exception e) {

        }

http://i64.tinypic.com/2qjybh4.png

http://i63.tinypic.com/flzwus.png

http://i63.tinypic.com/112g5fm.png


Show All Markers with Google map

In these Methods store all Markers and automatically zoom to show all markers in google map.

// Declare the Markers List.
List<MarkerOptions> markerList;
private BitmapDescriptor vnrPoint,banPoint;


public void storeAllMarkers()
{
      markerList=new ArrayList<>();
      markerList.removeAll(markerList);


      // latitude and longitude of Virudhunagar

      double latitude1=9.587209;
      double longitude1=77.951431;
   vnrPoint=BitmapDescriptorFactory.fromResource(R.drawable.location_icon_1);
      LatLng vnr = new LatLng(latitude1, longitude1);
      MarkerOptions vnrMarker = new MarkerOptions();
      vnrMarker.position(vnr);
      vnrMarker.icon(vnrPoint);
      markerList.add(vnrMarker);

      // latitude and longitude of Bengaluru

      double latitude2=12.972442;
      double longitude2=77.580643;

    banPoint=BitmapDescriptorFactory.fromResource(R.drawable.location_icon_2);

      LatLng ban = new LatLng(latitude2, longitude2);
      MarkerOptions bengalureMarker = new MarkerOptions();
      bengalureMarker.position(ban);
      bengalureMarker.icon(banPoint);
      markerList.add(bengalureMarker);

      // You can add any numbers of MarkerOptions like this.

     showAllMarkers();

 }


public void showAllMarkers()
{
    LatLngBounds.Builder builder = new LatLngBounds.Builder();

    for (MarkerOptions m : markerList) {
        builder.include(m.getPosition());
    }

    LatLngBounds bounds = builder.build();

    int width = getResources().getDisplayMetrics().widthPixels;
    int height = getResources().getDisplayMetrics().heightPixels;
    int padding = (int) (width * 0.30); 

    // Zoom and animate the google map to show all markers

    CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, width, height, padding);
    googleMap.animateCamera(cu);
}

So

I needed to use addOnGlobalLayoutListener to get the appropriate sample

for example, your Google Map is inside RelativeLayout:

RelativeLayout mapLayout = (RelativeLayout)findViewById(R.id.map_layout);
mapLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            //and write code, which you can see in answer above
        }
    });

Examples related to android

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How to implement a simple scenario the OO way My eclipse won't open, i download the bundle pack it keeps saying error log getting " (1) no such column: _id10 " error java doesn't run if structure inside of onclick listener Cannot retrieve string(s) from preferences (settings) strange error in my Animation Drawable how to put image in a bundle and pass it to another activity FragmentActivity to Fragment A failure occurred while executing com.android.build.gradle.internal.tasks

Examples related to google-maps

GoogleMaps API KEY for testing Google Maps shows "For development purposes only" java.lang.NoClassDefFoundError:failed resolution of :Lorg/apache/http/ProtocolVersion How to import JSON File into a TypeScript file? Googlemaps API Key for Localhost Getting "Cannot call a class as a function" in my React Project ERROR: Google Maps API error: MissingKeyMapError This page didn't load Google Maps correctly. See the JavaScript console for technical details Google Maps API warning: NoApiKeys ApiNotActivatedMapError for simple html page using google-places-api

Examples related to google-maps-api-2

Android map v2 zoom to show all the markers Find distance between two points on map using Google Map API V2 Google Maps v2 - set both my location and zoom in Set Google Maps Container DIV width and height 100% Add Marker function with Google Maps API How can I change the color of a Google Maps marker?

Examples related to google-maps-android-api-2

How can I show current location on a Google Map on Android Marshmallow? Adding Google Play services version to your app's manifest? Android Google Maps API V2 Zoom to Current Location How to draw interactive Polyline on route google maps v2 android How to display my location on Google Maps for Android API v2 Android map v2 zoom to show all the markers How to create a custom-shaped bitmap marker with Android map API v2 Draw path between two points using Google Maps Android API v2 How to download Google Play Services in an Android emulator? Get driving directions using Google Maps API v2