315 votes

Android map v2 zoomer pour afficher tous les marqueurs

J'ai 10 marqueurs dans le GoogleMap . Je veux zoomer le plus possible et garder tous les marqueurs en vue ? Dans la version précédente, il est possible de le faire à partir de zoomToSpan() mais dans la v2, je n'ai aucune idée de la manière de procéder. De plus, je connais le rayon du cercle qui doit être visible.

871voto

andr Points 5822

Vous devez utiliser l' CameraUpdate classe à faire (probablement) tous programmatiques les mouvements de carte.

Pour ce faire, il faut d'abord calculer les limites de tous les marqueurs de la sorte:

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

Ensuite, obtenir un mouvement de la description de l'objet à l'aide de l'usine: CameraUpdateFactory:

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

Enfin déplacer la carte:

googleMap.moveCamera(cu);

Ou si vous voulez une animation:

googleMap.animateCamera(cu);

C'est tout :)

Précisions 1

Presque tous les mouvements méthodes nécessitent l' Map objet à avoir passé le processus d'implantation. Vous pouvez attendre pour que cela se produise à l'aide de l' addOnGlobalLayoutListener construire. Les détails peuvent être trouvés dans les commentaires de cette réponse et de réponses qui restent. Vous pouvez également trouver un code complet pour le réglage de l'étendue de la carte à l'aide de addOnGlobalLayoutListener ici.

Clarification 2

Un commentaire note que l'utilisation de cette méthode pour un seul marqueur de résultats dans la carte zoom réglé à une "bizarre" niveau de zoom (qui je crois doit être maximale de niveau de zoom disponibles pour une position donnée). Je pense que c'est normal car:

  1. L' LatLngBounds bounds instance ont northeast propriété est égale à southwest, ce qui signifie que la partie de la zone de la terre couverte par le présent bounds est exactement zéro. (Ce qui est logique, car un seul marqueur n'a pas de zone.)
  2. En passant bounds de CameraUpdateFactory.newLatLngBounds vous demande un calcul d'un tel niveau de zoom que l' bounds (ayant zéro de la zone) pour l'ensemble de la vue de la carte.
  3. Vous pouvez effectuer ce calcul sur un morceau de papier. Le théorique, le niveau de zoom qui est la réponse est +∞ (infinity positive). Dans la pratique, l' Map objet ne gère pas cette valeur, elle est ramenée à un niveau plus raisonnable niveau maximum autorisé pour un emplacement donné.

Une autre façon de le dire: comment peut - Map objet de savoir quel niveau de zoom doit-il choisir pour un seul endroit? Peut-être que la valeur optimale devrait être de 20 (si elle représente une adresse spécifique). Ou peut-être 11 (si elle représente une ville). Ou peut-être 6 (si elle représente un pays). L'API n'est pas que la smart et la décision est à vous.

Donc, vous devriez vérifier simplement si markers a qu'un seul endroit et dans ce cas, utilisez l'un des:

  • CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition()) - aller au marqueur de position, le congé de niveau de zoom actuel intact.
  • CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F) - aller au marqueur, réglez le niveau de zoom à été choisi arbitrairement la valeur 12.

21 votes

Il convient de noter que le déplacement ne peut pas se faire à partir des appels onCreate, la vue doit être créée. J'ai dû utiliser addOnGlobalLayoutListener pour obtenir l'exemple approprié.

6 votes

@Bar C'est en partie vrai. Pour être précis : certains les méthodes de déplacement ne fonctionneront pas immédiatement après la création de l'objet carte. La raison en est que l'objet map n'a pas été mesuré c'est-à-dire qu'il n'a pas encore subi le processus de mise en page. Une solution typique consiste à utiliser addOnGlobalLayoutListener() o post() avec un Runnable . C'est exactement la raison pour laquelle l'obtention des coordonnées de l'écran du marqueur ne peut pas se faire en onCreate - voir stackoverflow.com/q/14429877/1820695 Toutefois, vous puede utiliser certaines méthodes avant même que la mise en page n'ait eu lieu - par exemple. CameraUpdateFactory.newLatLngBounds() con 4 paramètres .

1 votes

J'ai essayé de le faire moi-même, de calculer manuellement les limites, et de zoomer pendant que le marqueur est dedans... ça fonctionnait plutôt mal, mais avec votre méthode simple, ça marche comme sur des roulettes. Merci beaucoup.

139voto

Zumry Mohamed Points 31

Google Map V2

La solution suivante fonctionne pour Android Marshmallow 6 (API 23, API 24, API 25, API 26, API 27, API 28). Elle fonctionne également dans 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);

14voto

chrjs Points 25

Je n'ai pas pu utiliser la fonction onGlobalLayoutlistener, voici donc une autre solution pour éviter l'apparition de ce type de problème. "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." erreur :

mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { 
@Override 
public void onMapLoaded() { 
    mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 15));
 } 
});

0 votes

Celui-ci prend beaucoup plus de temps que le OnGlobalLayoutListener, donc pour moi il affichait toujours la zone/zoom par défaut de la carte en premier, avant de déplacer la caméra selon mes besoins.

0 votes

Comment donner de l'espace à mes 2 marqueurs qui sont en contact avec les limites de la carte.

13voto

Eugene Voronoy Points 43

Donc

J'ai dû utiliser addOnGlobalLayoutListener pour obtenir l'exemple approprié.

par exemple, votre carte Google est dans 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
        }
    });

1 votes

Je suis venu ici depuis le tutoriel d'Udemy, excellent travail, ils ont utilisé votre réponse pour résoudre le problème.

9voto

BK19 Points 848

Cela fonctionne bien pour moi.

Ce code me permet d'afficher plusieurs marqueurs avec un zoom particulier sur l'écran de la carte.

// Variables déclarées

private LatLngBounds bounds;
private LatLngBounds.Builder builder;

// Méthode permettant d'ajouter plusieurs points de repère avec une icône à dessiner

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

    }

// Pour ajouter plusieurs marqueurs visibles sur la carte

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

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