setminzoompreference - Android map v2 zoom para mostrar todos los marcadores
zoom google maps android api (12)
Tengo 10 marcadores en el GoogleMap
. ¿Quiero ampliar lo más 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 idea de cómo hacerlo. Además, sé el radio del círculo que necesita ser visible.
Trabajando bien para mi
A partir de este código, estoy mostrando varios marcadores con un zoom particular en la pantalla del mapa.
// Variables declaradas
private LatLngBounds bounds;
private LatLngBounds.Builder builder;
// Método para agregar múltiples puntos de marcador 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 múltiples marcadores 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);
Google Map V2: Zoom MarkerOptions dentro de los límites La 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 mapa de Google 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
}
});
Debe usar la clase CameraUpdate
para realizar (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();
Luego obtenga un objeto de descripción de movimiento usando 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 configurar la extensión del mapa usando addOnGlobalLayoutListener
aquí .
Aclaración 2
Un comentario señala que el uso de este método solo para un marcador hace que el zoom del mapa se establezca en un nivel de zoom "extraño" (que creo que es el nivel de zoom máximo disponible para una ubicación determinada). Creo que esto se espera porque:
- La instancia de los
LatLngBounds bounds
tendrá una propiedadnortheast
igual alsouthwest
, lo que significa que la porción del área de la tierra cubierta por estosbounds
es exactamente cero. (Esto es lógico ya que un solo marcador no tiene área). - Al pasar los
bounds
aCameraUpdateFactory.newLatLngBounds
, esencialmente solicita un cálculo de tal nivel de zoom que losbounds
(que tienen área cero) cubrirán toda la vista del mapa. - Realmente 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 se fija a un nivel máximo más razonable permitido para una ubicación determinada.
Otra forma de decirlo: ¿cómo puede el objeto Mapear saber qué nivel de zoom debe elegir para una única ubicación ? Quizás el valor óptimo debería ser 20 (si representa una dirección específica). O tal vez 11 (si representa un pueblo). O tal vez 6 (si representa un país). API no es tan inteligente y la decisión depende de ti.
Por lo tanto, simplemente debe verificar si los markers
tienen solo una ubicación y, de ser así, usar uno de los siguientes:
-
CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition())
- ve a la posición del marcador, deja intacto el nivel de zoom actual. -
CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F)
: vaya a la posición del marcador, establezca el nivel de zoom en el valor elegido arbitrariamente 12.
No podría usar el onGlobalLayoutlistener, por lo 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));
}
});
Tengo otra manera de hacer esto mismo funciona perfectamente. así que la idea de mostrar todos los marcadores en la pantalla es que necesitamos un centro de latitud larga y nivel de zoom. Aquí está la función que le dará a ambos y necesitará todos los objetos latlng del marcador como entrada.
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);
}
Esta función devuelve el objeto Par que puede usar como
Par pair = getCenterWithZoomLevel (l1, l2, l3 ..); mGoogleMap.moveCamera (CameraUpdateFactory.newLatLngZoom (pair.first, pair.second));
puede en lugar de usar el relleno para alejar sus marcadores de los límites de la pantalla, puede ajustar el zoom en -1.
Tuve un problema similar, utilizando el siguiente código resuelto el problema:
CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 5)
generalmente 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
Utilice 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();
}
esto ayudaría .. desde 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));
}
});
}
}
Para información clara mira esta url. https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java
Mostrar todos los marcadores con Google map
En estos métodos, almacene todos los marcadores y haga zoom automáticamente para mostrar todos los marcadores en 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);
}
Nota : esto no es una solución a la pregunta original. Esta es una solución a uno de los subproblemas mencionados above .
Solución a la clarificación de @andr 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 de zoom máximo en este momento. Esto también puede suceder cuando hay más de 1 marcador, pero todos están muy cerca uno del otro. Entonces también ocurrirá el mismo problema.
Solución : suponga que desea que su mapa nunca supere los 16 niveles de zoom. Luego, después de hacer ...
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
mMap.moveCamera(cu);
Compruebe si su nivel de zoom ha cruzado el nivel 16 (o lo que quiera) -
float currentZoom = mMap.getCameraPosition().zoom;
Y si este nivel es mayor que 16, que solo lo será si hay muy pocos marcadores o si todos los marcadores están muy cerca uno del otro, simplemente aleja el mapa en esa posición en particular solo configurando el nivel de zoom en 16.
mMap.moveCamera(CameraUpdateFactory.zoomTo(16));
De esta manera nunca tendrá el problema del nivel de zoom "extraño" explicado muy bien por @andr también.
//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