J'utilise la nouvelle API Google Maps pour Android .
Je crée une activité qui inclut un MapFragment. Dans l'activité, onResume
je place les marqueurs dans l'objet GoogleMap, puis je définis un cadre de délimitation pour la carte qui comprend tous les marqueurs.
Cela utilise le pseudo code suivant:
LatLngBounds.Builder builder = new LatLngBounds.Builder();
while(data) {
LatLng latlng = getPosition();
builder.include(latlng);
}
CameraUpdate cameraUpdate = CameraUpdateFactory
.newLatLngBounds(builder.build(), 10);
map.moveCamera(cameraUpdate);
L'appel à map.moveCamera()
provoque le blocage de mon application avec la pile suivante:
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 - au lieu de la newLatLngBounds()
méthode d'usine, j'utilise la newLatLngZoom()
méthode, le même piège ne se produit pas.
Est-ce onResume
le meilleur endroit pour dessiner les marqueurs sur l'objet GoogleMap ou dois-je dessiner les marqueurs et définir la position de la caméra ailleurs?
setOnCameraChangeListener
est maintenant obsolèteCes réponses sont très bien, mais j'opterais pour une approche différente, plus simple. Si la méthode ne fonctionne qu'après la mise en page de la carte, attendez-la:
la source
OK, j'ai travaillé sur ça. Comme documenté ici, cette API ne peut pas être utilisée avant la mise en page.
L'API correcte à utiliser est décrite comme suit:
Pour résoudre le problème, j'ai calculé la taille de mon écran et fourni la largeur et la hauteur à
Cela m'a ensuite permis de spécifier la pré-mise en page de la boîte englobante.
la source
La solution est plus simple que ça ...
Attrapez
IllegalStateException
et utilisez plutôt l'écouteur global sur la vue. La définition de la taille liée à l'avance (pré-mise en page) à l'aide des autres méthodes signifie que vous devez calculer la taille de THE VIEW, pas celle du périphérique d'écran. Ils ne correspondent que si vous passez en plein écran avec votre carte et n'utilisez pas de fragments.la source
C'est ma solution, attendez que la carte soit chargée dans ce cas.
la source
L'ajout et la suppression de marqueurs peuvent être effectués avant la mise en page, mais le déplacement de la caméra ne peut pas (sauf en utilisant
newLatLngBounds(boundary, padding)
comme indiqué dans la réponse du PO).Probablement le meilleur endroit pour effectuer une mise à jour initiale de la caméra utilise un one-shot
OnGlobalLayoutListener
comme indiqué dans un exemple de code de Google , par exemple , voir l'extrait suivantsetUpMap()
en MarkerDemoActivity.java :la source
La réponse acceptée ne fonctionnait pas pour moi car je devais utiliser le même code à différents endroits de mon application.
Au lieu d'attendre que la caméra change, j'ai créé une solution simple basée sur la suggestion de Lee de spécifier la taille de la carte. C'est au cas où votre carte aurait la taille de l'écran.
J'espère que cela aide quelqu'un d'autre!
la source
La réponse acceptée est, comme indiqué dans les commentaires, un peu hacky. Après l'avoir implémenté, j'ai remarqué une quantité de
IllegalStateException
journaux plus acceptable dans l'analyse. La solution que j'ai utilisée est d'ajouter unOnMapLoadedCallback
dans lequel leCameraUpdate
est effectué. Le rappel est ajouté auGoogleMap
. Une fois votre carte chargée, la mise à jour de la caméra sera effectuée.Cela fait que la carte affiche brièvement la vue agrandie (0,0) avant d'effectuer la mise à jour de la caméra. Je pense que c'est plus acceptable que de provoquer des accidents ou de se fier à un comportement non documenté.
la source
utilise ça ça a marché pour moi
la source
Dans de très rares cas, la mise en page MapView est terminée, mais la mise en page GoogleMap n'est pas terminée,
ViewTreeObserver.OnGlobalLayoutListener
elle - même ne peut pas arrêter le plantage. J'ai vu le crash avec le package de services Google Play version 5084032. Ce cas rare peut être causé par le changement dynamique de la visibilité de mon MapView.Pour résoudre ce problème, j'EMBEDDED
GoogleMap.OnMapLoadedCallback
dansonGlobalLayout()
,la source
mapView.getViewTreeObserver()
en une variable locale l' erreur suivante se produit: "IllegalStateException: ce ViewTreeObserver n'est pas vivant, appelez à nouveau getViewTreeObserver ()" . Avez-vous essayé cela?J'ai utilisé une approche différente qui fonctionne pour les versions récentes du SDK Google Maps (9.6+) et basée sur onCameraIdleListener . Comme je le vois jusqu'à présent, c'est la méthode de rappel
onCameraIdle
appelée toujours aprèsonMapReady
. Donc, mon approche ressemble à ce morceau de code (compte tenu de sa mise en placeActivity
):la source
J'ai créé un moyen de combiner les deux rappels: onMapReady et onGlobalLayout en une seule observable qui n'émettra que lorsque les deux événements auront été déclenchés.
https://gist.github.com/abhaysood/e275b3d0937f297980d14b439a8e0d4a
la source
Ok, je suis confronté au même problème. J'ai mon fragment avec mon SupportmapFragment, ABS et le tiroir de navigation. Ce que j'ai fait était:
Et, en passant, je vous appelle
resetCamera()
deonCreateView
après gonflage et avant de retourner.Ce que cela fait, c'est attraper l'exception la première fois (alors que la carte "prend une taille" pour le dire ...) et ensuite, d'autres fois, je dois réinitialiser la caméra, la carte a déjà une taille et le fait par remplissage.
Le problème est expliqué dans la documentation , il est dit:
Je pense que c'est une solution assez décente. J'espère que ça aide quelqu'un.
la source
newLatLngBounds()
ou dansanimateCamera()
, ou dans les deux? La branche catch ne conduira-t-elle pas à une nouvelle exception?Si vous devez attendre le début des interactions utilisateur possibles, utilisez
OnMapLoadedCallback
comme décrit dans les réponses précédentes. Mais, si tout ce dont vous avez besoin est de fournir un emplacement par défaut pour la carte, aucune des solutions décrites dans ces réponses n'est nécessaire. Les deuxMapFragment
etMapView
peuvent accepter unGoogleMapOptions
au début qui peut fournir l'emplacement par défaut. La seule astuce est de ne pas les inclure directement dans votre layout car le système les appellera alors sans les options mais de les initialiser dynamiquement.Utilisez ceci dans votre mise en page:
et remplacez le fragment dans votre
onCreateView()
:En plus d'être plus rapide au démarrage, il n'y aura pas de carte du monde affichée en premier et un mouvement de caméra en second. La carte commencera directement avec l'emplacement spécifié.
la source
Une autre approche serait quelque chose comme (en supposant que votre vue la plus haute soit un FrameLayout nommé
rootContainer
, même si cela fonctionnera tant que vous choisissez toujours votre conteneur le plus haut, quel que soit son type ou son nom):Modification de vos fonctions de l' appareil au travail que si
layoutDone
est -true
résoudra tous vos problèmes sans avoir à ajouter des fonctions supplémentaires ou câbler logique aulayoutListener
gestionnaire.la source
J'ai trouvé que cela fonctionnait et était plus simple que les autres solutions:
Cela tente de nouveau l'appel après l'exécution de la mise en page. Pourrait probablement inclure une sécurité pour éviter une boucle infinie.
la source
Pourquoi ne pas simplement utiliser quelque chose comme ceci:
la source
newLatLngBounds(builder.build(), padding)
ne pas essayer-catch? Cette exception se produit-elle dansmoveCamera()
?Il existe une classe d'assistance dans le référentiel Google Maps que vous pouvez utiliser - elle attend que la mise en page et la carte soient prêtes avant de notifier un rappel avec GoogleMap:
La source originale est ici:
https://github.com/googlemaps/android-samples/blob/7ee737b8fd6d39c77f8b3716ba948e1ce3730e61/ApiDemos/java/app/src/main/java/com/example/mapdemo/OnMapAndViewReadyListener.java
Il existe également une implémentation Kotlin:
https://github.com/googlemaps/android-samples/blob/master/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/OnMapAndViewReadyListener.kt
la source
Comme indiqué dans OnCameraChangeListener () est obsolète ,
setOnCameraChangeListener
est désormais obsolète. Vous devriez donc le remplacer par l'une des trois méthodes suivantes:GoogleMap.OnCameraMoveStartedListener
GoogleMap.OnCameraMoveListener
GoogleMap.OnCameraIdleListener
Dans mon cas, je l'ai utilisé
OnCameraIdleListener
et à l'intérieur je l'ai retiré car il était invoqué encore et encore sur n'importe quel mouvement.METTRE À JOUR
J'ai supprimé
googleMap.setOnCameraIdleListener
dans mon projet, car il n'était parfois pas appelé lorsqu'une carte était affichée, mais conservégoogleMap.setOnCameraIdleListener(clusterManager)
.la source
J'ai eu la même erreur en essayant d'appeler mMap.animateCamera. Je l'ai résolu en appelant le rappel setOnMapLoadedCallback dans ma fonction onMapReady comme indiqué ci-dessous
Cela devrait fonctionner correctement.
la source