96 votes

moveCamera avec CameraUpdateFactory.newLatLngBounds se bloque

Je suis en train de faire l'utilisation de la nouvelle Android de Google Maps API.

J'ai créer une activité qui comprend un MapFragment. Dans l'activité onResume - je définir les marqueurs dans le GoogleMap objet, puis de définir un rectangle de délimitation de la carte qui comprend tous les marqueurs.

C'est à l'aide de la 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 à l' map.moveCamera() des causes de ma demande de collision 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 l' newLatLngBounds() usine méthode que j'utilise newLatLngZoom() méthode, puis le même piège ne se produit pas.

Est l' onResume le meilleur endroit pour tirer les marqueurs sur la GoogleMap objet ou devrais-je dessiner les marqueurs et le réglage de la position de la caméra à un autre endroit?

133voto

SteelRat Points 1464

Vous pouvez utiliser la méthode newLatLngBounds simple dans OnCameraChangeListener . Tout fonctionnera parfaitement et vous n'avez pas besoin de calculer la taille de l'écran. Cet événement se produit après le calcul de la taille de la carte (si j'ai bien compris).

Exemple:

 map.setOnCameraChangeListener(new OnCameraChangeListener() {

    @Override
    public void onCameraChange(CameraPosition arg0) {
        // Move camera.
        map.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 10));
        // Remove listener to prevent position reset on camera move.
        map.setOnCameraChangeListener(null);
    }
});
 

58voto

Leandro Points 241

Ces réponses sont très bien, mais je choisirais une approche différente, plus simple. Si la méthode ne fonctionne qu'après la mise en page de la carte, attendez simplement:

 map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
    @Override
    public void onMapLoaded() {
        map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 30));
    }
});
 

52voto

Lee Points 1541

OK j'ai travaillé. Comme indiqué ici que l'API ne peut pas être utilisé en pré-mise en page.

La bonne API à utiliser est décrite comme suit:

Remarque: utilisez Uniquement la méthode la plus simple newLatLngBounds(limite de remplissage) pour générer un CameraUpdate si elle va être utilisée pour déplacer le l'appareil après que la carte a subi de mise en page. Lors de la présentation, l'API calcule l'affichage des limites de la carte, qui sont nécessaires pour correctement projet de la boîte englobante. En comparaison, vous pouvez utiliser le CameraUpdate retourné par la méthode plus complexe newLatLngBounds(limite, la largeur, la hauteur de remplissage) à tout moment, même avant de la carte a subi de mise en page, parce que l'API calcule l' afficher les limites de l'argumentation que vous passez.

Pour résoudre le problème j'ai calculé ma taille de l'écran et à condition que la largeur et la hauteur de

public static CameraUpdate newLatLngBounds(
    LatLngBounds bounds, int width, int height, int padding)

Ensuite, cela m'a permis de spécifier la boîte englobante de pré-mise en page.

34voto

Daniele Segato Points 1281

La solution est plus simple que ça ....

 // Pan to see all markers in view.
try {
    this.gmap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
} catch (IllegalStateException e) {
    // layout not yet initialized
    final View mapView = getFragmentManager()
       .findFragmentById(R.id.map).getView();
    if (mapView.getViewTreeObserver().isAlive()) {
        mapView.getViewTreeObserver().addOnGlobalLayoutListener(
        new OnGlobalLayoutListener() {
            @SuppressWarnings("deprecation")
            @SuppressLint("NewApi")
            // We check which build version we are using.
            @Override
            public void onGlobalLayout() {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                    mapView.getViewTreeObserver()
                        .removeGlobalOnLayoutListener(this);
                } else {
                    mapView.getViewTreeObserver()
                        .removeOnGlobalLayoutListener(this);
                }
                gmap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
            }
        });
    }
}
 

Catch IllegalStateException et utilisez plutôt l'écouteur global de la vue. Définir la taille de la reliure à l’avance (pré-agencement) à l’aide des autres méthodes signifie que vous devez calculer la taille de THE VIEW et non celle du périphérique d’écran. Ils ne correspondent que si vous allez en plein écran avec votre carte et n'utilisez pas de fragments.

14voto

StephenT Points 195

L'ajout et la suppression des marqueurs peut être fait de pré-mise en page d'achèvement, mais le déplacement de la caméra ne peut pas (sauf à l'aide d' newLatLngBounds(boundary, padding) comme indiqué dans le cas des OP de réponse).

Probablement le meilleur endroit pour effectuer une première caméra mise à jour à l'aide d'un one-shot OnGlobalLayoutListener comme indiqué dans Google exemple de code, voir, par exemple, l'extrait suivant d' setUpMap() dans MarkerDemoActivity.java:

// 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.getViewTreeObserver().isAlive()) {
    mapView.getViewTreeObserver().addOnGlobalLayoutListener(
    new OnGlobalLayoutListener() {
        @SuppressLint("NewApi") // We check which build version we are using.
        @Override
        public void onGlobalLayout() {
            LatLngBounds bounds = new LatLngBounds.Builder()
                    .include(PERTH)
                    .include(SYDNEY)
                    .include(ADELAIDE)
                    .include(BRISBANE)
                    .include(MELBOURNE)
                    .build();
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
              mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } else {
              mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
            mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50));
        }
    });
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X