Mapa Android v2 zoom para mostrar todos los marcadores

Tengo 10 marcadores en GoogleMap . Quiero acercarme tanto como sea posible y tener todos los marcadores a la vista? En la versión anterior, esto se puede lograr desde zoomToSpan() pero en v2 no tengo ni idea de cómo hacerlo. Además, sé el radio del círculo que debe ser visible.

Debe usar la clase CameraUpdate para hacer (probablemente) todos los movimientos de mapas programáticos.

Para hacer esto, primero calcule los límites de todos los marcadores así:

 LatLngBounds.Builder builder = new LatLngBounds.Builder(); for (Marker marker : markers) { builder.include(marker.getPosition()); } LatLngBounds bounds = builder.build(); 

A continuación, obtenga un objeto de descripción de movimiento utilizando la fábrica: CameraUpdateFactory :

 int padding = 0; // offset from edges of the map in pixels CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding); 

Finalmente mueva el mapa:

 googleMap.moveCamera(cu); 

O si quieres una animación:

 googleMap.animateCamera(cu); 

Eso es todo 🙂

Aclaración 1

Casi todos los métodos de movimiento requieren que el objeto Map haya pasado el proceso de diseño. Puede esperar a que esto suceda utilizando la construcción addOnGlobalLayoutListener . Los detalles se pueden encontrar en los comentarios a esta respuesta y las respuestas restantes. También puede encontrar un código completo para establecer la extensión del mapa usando addOnGlobalLayoutListener aquí .

Aclaración 2

Un comentario señala que el uso de este método para un solo marcador da como resultado que el zoom del mapa se establezca en un nivel de zoom “extraño” (que creo que es el nivel máximo de zoom disponible para una ubicación determinada). Creo que esto se espera porque:

  1. La instancia de los LatLngBounds bounds tendrá una propiedad northeast equivalente al southwest , lo que significa que la porción del área de la tierra cubierta por estos bounds es exactamente cero. (Esto es lógico ya que un solo marcador no tiene área).
  2. Al pasar los bounds a CameraUpdateFactory.newLatLngBounds , básicamente se solicita un cálculo de dicho nivel de zoom para que los bounds (que tienen un área cero) cubran toda la vista del mapa.
  3. En realidad, puede realizar este cálculo en una hoja de papel. El nivel de zoom teórico que es la respuesta es + ∞ (infinito positivo). En la práctica, el objeto Map no admite este valor, por lo que está sujeto a un nivel máximo más razonable permitido para una ubicación dada.

Otra forma de decirlo: ¿cómo puede el objeto Map saber qué nivel de zoom debe elegir para una sola ubicación ? Tal vez el valor óptimo debería ser 20 (si representa una dirección específica). O tal vez 11 (si representa una ciudad). O tal vez 6 (si representa un país). La API no es tan inteligente y la decisión depende de usted.

Entonces, simplemente debes verificar si los markers tienen solo una ubicación y, de ser así, usa uno de los siguientes:

  • CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition()) – ir a la posición del marcador, dejar intacto el nivel de zoom actual.
  • CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F) – ir a la posición del marcador, establecer el nivel de zoom al valor arbitrariamente elegido 12.

Google Map V2: Zoom MarkerOptions dentro de los límites Mejor solución de trabajo para Android Marshmallow 6 (API 23, API 24, API 25), también funciona en 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); 

Asi que

Necesitaba usar addOnGlobalLayoutListener para obtener la muestra adecuada

por ejemplo, su Google Map está dentro de 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 } }); 

No pude usar el onGlobalLayoutlistener, así que aquí hay otra solución para evitar que "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)); } }); 

Funciona bien para mí.

Desde este código, estoy mostrando múltiples marcadores con un zoom particular en la pantalla del mapa.

// Variables declaradas

 private LatLngBounds bounds; private LatLngBounds.Builder builder; 

// Método para agregar puntos de marcadores múltiples con un icono dibujable

 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()); } 

// Para agregar marcadores múltiples visibles en el mapa

 @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); 

Nota : esta no es una solución a la pregunta original. Esta es una solución a uno de los subproblemas discutidos anteriormente .

Solución a @andr Aclaración 2

Es realmente problemático cuando solo hay un marcador en los límites y debido a ello el nivel de zoom se establece en un nivel muy alto ( nivel 21 ). Y Google no proporciona ninguna forma de establecer el nivel máximo de zoom en este punto. Esto también puede suceder cuando hay más de 1 marcador, pero todos están muy cerca el uno del otro. Entonces también ocurrirá el mismo problema.

Solución : suponga que desea que su mapa nunca vaya más allá del nivel de zoom 16. Luego después de hacer –

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

Comprueba si tu nivel de zoom ha cruzado el nivel 16 (o lo que quieras) –

 float currentZoom = mMap.getCameraPosition().zoom; 

Y si este nivel es mayor que 16, que solo será si hay muy pocos marcadores o si todos los marcadores están muy cerca el uno del otro, simplemente aleje el mapa en esa posición particular solo marcando el nivel de zoom en 16.

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

De esta forma, nunca se le explicará muy bien el problema del nivel de zoom “extraño” con @andr.

esto ayudaría … desde demos de Google apis

 private List 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)); } }); } } 

para obtener información clara, mira esta url. https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java

Tuve un problema similar, usando el siguiente código resolvió el problema:

CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 5) general, las diferencias de ubicación en mi caso no son más que dos ciudades vecinas.

zoom para adaptarse a todos los marcadores en el mapa google maps v2

Use el método “getCenterCoordinate” para obtener la coordenada central y usarla en 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(); } 

Tengo otra forma de hacer lo mismo que funciona perfectamente. entonces la idea detrás de mostrar todos los marcadores en la pantalla, necesitamos un centro de latitud larga y un nivel de zoom. aquí está la función que les dará a ambos y necesitará todos los objetos Latlng del marcador como entrada.

  public Pair 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(center, zoom); } 

Esta función devuelve el objeto Pair que puedes usar como

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

En lugar de utilizar el relleno para alejar los marcadores de los límites de la pantalla, puede ajustar el zoom en -1.

  //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://sofes.miximages.com/android/2qjybh4.png

http://sofes.miximages.com/android/flzwus.png

http://sofes.miximages.com/android/112g5fm.png