web-dev-qa-db-fra.com

Android map v2 zoomer pour afficher tous les marqueurs

J'ai 10 marqueurs dans le GoogleMap. Je veux faire un zoom avant et garder tous les marqueurs en vue? Dans la version précédente, ceci pouvait être obtenu à partir de zoomToSpan(), mais je ne sais absolument pas comment faire cela. De plus, je connais le rayon du cercle qui doit être visible.

269
Asanka Senavirathna

Vous devez utiliser la classe CameraUpdate pour effectuer (probablement) tous les mouvements de carte programmatiques.

Pour ce faire, calculez d’abord les bornes de tous les marqueurs comme ceci:

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

Obtenez ensuite un objet de description de mouvement en utilisant la fabrique: CameraUpdateFactory:

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

Enfin déplacez la carte:

googleMap.moveCamera(cu);

Ou si vous voulez une animation:

googleMap.animateCamera(cu);

C'est tout :)

Clarification 1

Presque toutes les méthodes de déplacement nécessitent que l'objet Map ait réussi le processus de présentation. Vous pouvez attendre que cela se produise en utilisant la construction addOnGlobalLayoutListener. Les détails peuvent être trouvés dans les commentaires à cette réponse et les réponses restantes. Vous pouvez également trouver un code complet pour définir 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 entraîne un zoom de la carte défini sur un niveau de zoom "bizarre" (qui, à mon avis, correspond au niveau de zoom maximal disponible pour un emplacement donné). Je pense que cela est prévu parce que:

  1. L'instance LatLngBounds bounds aura la propriété northeast égale à southwest, ce qui signifie que la partie de la surface de la terre couverte par cette bounds vaut exactement zéro. (Ceci est logique puisqu'un seul marqueur n'a pas de surface.)
  2. En passant bounds à CameraUpdateFactory.newLatLngBounds, vous demandez essentiellement un calcul d'un niveau de zoom tel que bounds (ayant une surface nulle) couvre toute la vue de la carte.
  3. Vous pouvez réellement effectuer ce calcul sur un morceau de papier. Le niveau de zoom théorique auquel la réponse est donnée est + ∞ (infini positif). En pratique, l'objet Map ne prend pas cette valeur en charge, il est donc limité à un niveau maximal plus raisonnable autorisé pour un emplacement donné.

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

Donc, vous devriez simplement vérifier si markers n'a qu'un seul emplacement et si oui, utilisez l'un des:

  • CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition()) - aller à la position du marqueur, laisser le niveau de zoom actuel intact.
  • CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F) - allez à la position du marqueur, réglez le niveau de zoom sur une valeur choisie arbitrairement 12.
766
andr

Google Map V2

La solution suivante fonctionne pour Android Marshmallow 6 (API 23, API 24, API 25, API 26, API 27, API 28). Cela fonctionne aussi à 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);
110
Zumry Mohamed

Je ne pouvais pas utiliser onGlobalLayoutlistener, voici donc une autre solution pour éviter l'erreur "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.":

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

Alors

J'avais besoin d'utiliser addOnGlobalLayoutListener pour obtenir l'échantillon approprié

par exemple, votre carte Google se trouve 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
        }
    });
13
Eugene Voronoy

Travailler bien pour moi.

À partir de ce code, j'affiche 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 pour ajouter plusieurs points de repère avec une icône pouvant être dessinée

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);
8
BK19

Remarque - Ce n'est pas une solution à la question d'origine. C'est une solution à l'un des sous-problèmes discutés ci-dessus .

Solution à @andr Clarification 2 -

C'est vraiment problématique quand il n'y a qu'un seul marqueur dans les limites et à cause de cela, le niveau de zoom est réglé sur un niveau très élevé ( niveau 21 ). Et Google ne fournit aucun moyen de définir le niveau de zoom maximal à ce stade. Cela peut aussi arriver quand il y a plus d'un marqueur mais qu'ils sont tous assez proches les uns des autres. Ensuite, le même problème se produira.

Solution - Supposons que votre carte ne dépasse jamais le niveau de zoom de 16. Puis après avoir fait -

CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
mMap.moveCamera(cu);

Vérifiez si votre niveau de zoom a franchi le niveau 16 (ou celui que vous souhaitiez) -

float currentZoom = mMap.getCameraPosition().zoom;

Et si ce niveau est supérieur à 16, ce qui ne le sera que s'il y a très peu de marqueurs ou si tous les marqueurs sont très proches les uns des autres, il vous suffit alors de faire un zoom arrière sur votre carte à cette position en définissant le niveau de zoom sur 16.

mMap.moveCamera(CameraUpdateFactory.zoomTo(16));

De cette façon, vous n'aurez jamais le problème de niveau de zoom "bizarre" expliqué très bien par @andr aussi.

3
Jyotman Singh

cela aiderait .. de 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));
                }
            });
        }
    }

pour des informations claires, regardez cette URL. https://github.com/googlemaps/Android-samples/blob/master/ApiDemos/app/src/main/Java/com/example/mapdemo/MarkerDemoActivity.Java

2
Amit Tumkur

J'ai eu un problème similaire, en utilisant le code suivant a résolu le problème:

CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 5) généralement les différences d'emplacement dans mon cas ne sont pas plus de deux villes voisines.

zoom pour adapter tous les marqueurs sur la carte google maps v2

1
Avishkar Ramjeet

Afficher tous les marqueurs avec Google map

Dans ces méthodes, stockez tous les marqueurs et effectuez automatiquement un zoom pour afficher tous les marqueurs dans 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);
}
0
Sathish kumar T.M

Utilisez la méthode "getCenterCoordinate" pour obtenir la coordonnée centrale et l'utiliser dans 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();
}

J'ai une autre façon de faire cette même chose fonctionne parfaitement. L’idée derrière tous les marqueurs à l’écran est donc d’avoir besoin d’un centre de hauteur et d’un niveau de zoom. voici la fonction qui vous donnera les deux et qui nécessite l’entrée de tous les objets Latlng du marqueur.

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

Cette fonction retourne l’objet Pair que vous pouvez utiliser comme

Pair pair = getCenterWithZoomLevel (l1, l2, l3 ..); mGoogleMap.moveCamera (CameraUpdateFactory.newLatLngZoom (pair.first, pair.second));

vous pouvez au lieu d’utiliser un rembourrage pour éloigner vos marqueurs des limites de l’écran, vous pouvez ajuster le zoom de -1.

0
Anuj Jindal