Estoy utilizando la nueva API de Google Maps para Android .
Creo una actividad que incluye un MapFragment. En la actividad onResume
, configuro los marcadores en el objeto GoogleMap y luego defino un cuadro delimitador para el mapa que incluye todos los marcadores.
Esto está usando el siguiente pseudo código:
LatLngBounds.Builder builder = new LatLngBounds.Builder();
while(data) {
LatLng latlng = getPosition();
builder.include(latlng);
}
CameraUpdate cameraUpdate = CameraUpdateFactory
.newLatLngBounds(builder.build(), 10);
map.moveCamera(cameraUpdate);
La llamada a map.moveCamera()
hace que mi aplicación se bloquee con la siguiente pila:
Caused by: java.lang.IllegalStateException:
Map size should not be 0. Most likely, layout has not yet
at maps.am.r.b(Unknown Source)
at maps.y.q.a(Unknown Source)
at maps.y.au.a(Unknown Source)
at maps.y.ae.moveCamera(Unknown Source)
at com.google.android.gms.maps.internal.IGoogleMapDelegate$Stub
.onTransact(IGoogleMapDelegate.java:83)
at android.os.Binder.transact(Binder.java:310)
at com.google.android.gms.maps.internal.IGoogleMapDelegate$a$a
.moveCamera(Unknown Source)
at com.google.android.gms.maps.GoogleMap.moveCamera(Unknown Source)
at ShowMapActivity.drawMapMarkers(ShowMapActivity.java:91)
at ShowMapActivity.onResume(ShowMapActivity.java:58)
at android.app.Instrumentation
.callActivityOnResume(Instrumentation.java:1185)
at android.app.Activity.performResume(Activity.java:5182)
at android.app.ActivityThread
.performResumeActivity(ActivityThread.java:2732)
Si, en lugar del newLatLngBounds()
método de fábrica, uso el newLatLngZoom()
método, entonces no ocurre la misma trampa.
¿Es el onResume
mejor lugar para dibujar los marcadores en el objeto GoogleMap o debería dibujar los marcadores y establecer la posición de la cámara en otro lugar?
setOnCameraChangeListener
ahora está en desusoEsas respuestas están bien, pero yo optaría por un enfoque diferente, uno más simple. Si el método solo funciona después de diseñar el mapa, solo espere:
fuente
OK, resolví esto. Como se documenta aquí, la API no se puede utilizar antes del diseño.
La API correcta para usar se describe como:
Para solucionar el problema, calculé el tamaño de mi pantalla y proporcioné el ancho y el alto para
Esto me permitió especificar el diseño previo del cuadro delimitador.
fuente
La solución es más simple que eso ...
En su lugar, captura
IllegalStateException
y usa el oyente global en la vista. Establecer el tamaño del límite por adelantado (diseño previo) utilizando los otros métodos significa que debe calcular el tamaño de LA VISTA, no el dispositivo de pantalla. Solo coinciden si vas a pantalla completa con tu mapa y no usas fragmentos.fuente
Esta es mi solución, solo espere hasta que se cargue el mapa en ese caso.
fuente
La adición y eliminación de marcadores se puede realizar antes de completar el diseño, pero no se puede mover la cámara (excepto usando
newLatLngBounds(boundary, padding)
como se indica en la respuesta del OP).Probablemente el mejor lugar para llevar a cabo una actualización inicial de la cámara utiliza un one-shot
OnGlobalLayoutListener
como se muestra en el código de ejemplo de Google , por ejemplo, véase el siguiente extracto desetUpMap()
en MarkerDemoActivity.java :fuente
La respuesta aceptada no me funcionaría porque tuve que usar el mismo código en varios lugares de mi aplicación.
En lugar de esperar a que cambiara la cámara, creé una solución simple basada en la sugerencia de Lee de especificar el tamaño del mapa. Esto es en caso de que su mapa sea del tamaño de la pantalla.
¡Espero que ayude a alguien más!
fuente
La respuesta aceptada es, como se señala en los comentarios, un poco hacky. Después de implementarlo, noté una cantidad de
IllegalStateException
registros superior a la aceptable en análisis. La solución que utilicé es agregar unOnMapLoadedCallback
en el queCameraUpdate
se realiza el. La devolución de llamada se agrega alGoogleMap
. Una vez que su mapa se cargue por completo, se realizará la actualización de la cámara.Esto hace que el mapa muestre brevemente la vista alejada (0,0) antes de realizar la actualización de la cámara. Sin embargo, creo que esto es más aceptable que causar accidentes o depender de un comportamiento indocumentado.
fuente
usa esto funcionó para mí
fuente
En casos muy raros, el diseño de MapView está terminado, pero el diseño de GoogleMap no está terminado,
ViewTreeObserver.OnGlobalLayoutListener
sí mismo no puede detener el bloqueo. Vi el bloqueo con el paquete de servicios de Google Play versión 5084032. Este caso poco común puede deberse al cambio dinámico de la visibilidad de mi MapView.Para resolver este problema, incrustado
GoogleMap.OnMapLoadedCallback
enonGlobalLayout()
,fuente
mapView.getViewTreeObserver()
en una variable local, se produce el siguiente error : "IllegalStateException: este ViewTreeObserver no está vivo, llame a getViewTreeObserver () de nuevo" . ¿Intentaste esto?Utilicé un enfoque diferente que funciona para versiones recientes de Google Maps SDK (9.6+) y basado en onCameraIdleListener . Como veo hasta ahora, el método de devolución de llamada se
onCameraIdle
llama siempre despuésonMapReady
. Entonces, mi enfoque se parece a este fragmento de código (considerando que está incluidoActivity
):fuente
Creé una forma de combinar las dos devoluciones de llamada: onMapReady y onGlobalLayout en un solo observable que se emitirá solo cuando ambos eventos se hayan activado.
https://gist.github.com/abhaysood/e275b3d0937f297980d14b439a8e0d4a
fuente
Ok, estoy enfrentando el mismo problema. Tengo mi fragmento con mi SupportmapFragment, ABS y cajón de navegación. Lo que hice fue:
Y, por cierto, llamo
resetCamera()
desdeonCreateView
después de inflar y antes de regresar.Lo que hace es captar la excepción la primera vez (mientras que el mapa "adquiere un tamaño" como una forma de decirlo ...) y luego, otras veces necesito reiniciar la cámara, el mapa ya tiene tamaño y lo hace mediante el relleno.
El problema se explica en la documentación , dice:
Creo que es una solución bastante decente. Espero que ayude a alguien.
fuente
newLatLngBounds()
o enanimateCamera()
, o en ambos? ¿No conducirá el catch-branch a una nueva excepción?Si necesita esperar a que comiencen las posibles interacciones del usuario, utilice
OnMapLoadedCallback
como se describe en las respuestas anteriores. Pero, si todo lo que necesita es proporcionar una ubicación predeterminada para el mapa, no hay necesidad de ninguna de las soluciones descritas en esas respuestas. AmbosMapFragment
yMapView
pueden aceptar unGoogleMapOptions
inicio que puede proporcionar la ubicación predeterminada correctamente. El único truco es no incluirlos directamente en su diseño porque el sistema los llamará sin las opciones en ese momento, sino inicializarlos dinámicamente.Use esto en su diseño:
y reemplace el fragmento en su
onCreateView()
:Además de ser más rápido para comenzar, no se mostrará un mapa del mundo primero y una cámara se moverá en segundo lugar. El mapa comenzará directamente con la ubicación especificada.
fuente
Otro enfoque sería algo como (Suponiendo que su vista superior es un FrameLayout nombrado
rootContainer
, aunque funcionará siempre que siempre elija su contenedor superior sin importar qué tipo o nombre tenga):Modificar las funciones de su cámara para que solo funcionen si
layoutDone
es asítrue
resolverá todos sus problemas sin tener que agregar funciones adicionales o conectar la lógica allayoutListener
controlador.fuente
Encontré que esto funciona y es más simple que las otras soluciones:
Esto intenta la llamada nuevamente después de que se haya ejecutado el diseño. Probablemente podría incluir una seguridad para evitar un bucle infinito.
fuente
¿Por qué no usar algo como esto?
fuente
newLatLngBounds(builder.build(), padding)
no está adentro try-catch? ¿Esta excepción ocurre enmoveCamera()
?Hay una clase auxiliar en el repositorio de Google Maps que puede aprovechar: espera que tanto el diseño como el mapa estén listos antes de notificar una devolución de llamada con GoogleMap:
La fuente original está aquí:
https://github.com/googlemaps/android-samples/blob/7ee737b8fd6d39c77f8b3716ba948e1ce3730e61/ApiDemos/java/app/src/main/java/com/example/mapdemo/OnMapAndViewReadyListener.java
También hay una implementación de Kotlin:
https://github.com/googlemaps/android-samples/blob/master/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/OnMapAndViewReadyListener.kt
fuente
Como se indica en OnCameraChangeListener () está en desuso ,
setOnCameraChangeListener
ahora está en desuso. Por lo tanto, debe reemplazarlo con uno de los tres mtehods:GoogleMap.OnCameraMoveStartedListener
GoogleMap.OnCameraMoveListener
GoogleMap.OnCameraIdleListener
En mi caso lo usé
OnCameraIdleListener
y por dentro lo quité porque se invocaba una y otra vez ante cualquier movimiento.ACTUALIZAR
Lo eliminé
googleMap.setOnCameraIdleListener
en mi proyecto, porque a veces no se llamaba cuando se mostraba un mapa, pero se conservabagoogleMap.setOnCameraIdleListener(clusterManager)
.fuente
Tuve el mismo error al intentar llamar a mMap.animateCamera. Lo resolví llamando a setOnMapLoadedCallback callback en mi función onMapReady como se muestra a continuación
Esto debería funcionar bien.
fuente