Android map v2 zoom, aby pokazać wszystkie znaczniki

Mam 10 markerów w GoogleMap. Chcę powiększyć jak najwięcej i zachować wszystkie znaczniki w widoku? We wcześniejszej wersji można to osiągnąć z zoomToSpan(), ale w v2 nie mam pojęcia, jak to zrobić. Co więcej, Znam promień okręgu, który musi być widoczny.

Author: JJD, 2013-02-12

13 answers

Powinieneś użyć klasy CameraUpdate do wykonywania (prawdopodobnie) wszystkich programowych ruchów map.

Aby to zrobić, najpierw Oblicz granice wszystkich markerów tak:

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

Następnie uzyskaj obiekt opisu ruchu za pomocą fabryki: CameraUpdateFactory:

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

Wreszcie przenieś mapę:

googleMap.moveCamera(cu);

Lub jeśli chcesz animację:

googleMap.animateCamera(cu);

To wszystko:)

Wyjaśnienie 1

Prawie wszystkie metody ruchu wymagają, aby obiekt Map miał przeszedł proces układ. Możesz poczekać na to, używając addOnGlobalLayoutListener construct. Szczegóły można znaleźć w komentarzach do tej odpowiedzi i pozostałych odpowiedzi. Możesz również znaleźć kompletny kod do ustawiania zakresu mapy za pomocą addOnGlobalLayoutListener tutaj.

Wyjaśnienie 2

Jeden komentarz zauważa, że użycie tej metody tylko dla jednego znacznika powoduje ustawienie powiększenia mapy na "dziwaczny" poziom powiększenia (który moim zdaniem jest maksymalnym poziomem powiększenia dostępnym dla danej lokalizacji). Myślę, że to jest oczekiwane ponieważ:

  1. instancja LatLngBounds bounds będzie miała właściwość northeast równą southwest, co oznacza, że część powierzchni Ziemi objęta tą bounds jest dokładnie równa zeru. (Jest to logiczne, ponieważ pojedynczy znacznik nie ma obszaru.)
  2. przechodząc bounds do CameraUpdateFactory.newLatLngBounds zasadniczo żądasz obliczenia takiego poziomu powiększenia, że bounds (z zerowym obszarem) pokryje cały widok mapy.
  3. można faktycznie wykonać te obliczenia na kartce papieru. Teoretyczny zoom poziom, który jest odpowiedzią to + ∞ (dodatnia nieskończoność). W praktyce obiekt Map nie obsługuje tej wartości, więc jest zaciśnięty do bardziej rozsądnego maksymalnego poziomu dozwolonego dla danej lokalizacji.

Inaczej mówiąc: skąd Map obiekt może wiedzieć, jaki poziom powiększenia powinien wybrać dla pojedynczej lokalizacji? Może optymalna wartość powinna wynosić 20 (jeśli reprezentuje konkretny adres). A może 11 (jeśli reprezentuje miasto). A może 6 (jeśli reprezentuje państwo). API to nie to mądrze i decyzja należy do ciebie.

Więc, należy po prostu sprawdzić, czy markers ma tylko jedną lokalizację, a jeśli Tak, użyj jednego z:

  • CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition()) - przejdź do pozycji znacznika, pozostaw aktualny poziom powiększenia nienaruszony.
  • CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F) - przejdź do pozycji znacznika, ustaw poziom powiększenia na dowolnie wybraną wartość 12.
 837
Author: andr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:30

Google Map V2

Poniższe rozwiązanie działa dla Androida Marshmallow 6 (API 23, API 24, API 25, API 26, API 27, API 28). Działa również w 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);
 130
Author: Zumry Mohamed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-20 11:37:01

Więc

Musiałem użyć addOnGlobalLayoutListener, aby uzyskać odpowiednią próbkę

Na przykład, Twoja mapa Google jest wewnątrz 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
Author: Eugene Voronoy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-04 11:43:49

Nie mogłem użyć onGlobalLayoutlistener, więc tutaj jest inne rozwiązanie, aby zapobiec "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." błąd:

mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { 
@Override 
public void onMapLoaded() { 
    mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 15));
 } 
});
 13
Author: chrjs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-15 08:31:48
Dla mnie działa dobrze.

Z tego kodu wyświetlam wiele znaczników ze szczególnym powiększeniem na ekranie mapy.

// zmienne Deklarowane

private LatLngBounds bounds;
private LatLngBounds.Builder builder;

/ / metoda dodawania wielu punktów znacznika z rysowalną ikoną

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

    }

// do dodawania wielu znaczników widocznych na mapie

@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);
 9
Author: BK19,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-05 11:20:37

Uwaga - nie jest to rozwiązanie pierwotnego pytania. Jest to rozwiązanie jednego z podproblemów omówionych powyżej.

Rozwiązanie @ andr Wyjaśnienie 2 -

Jest to naprawdę problematyczne, gdy w granicach jest tylko jeden znacznik, a dzięki temu poziom powiększenia jest ustawiony na bardzo wysoki (Poziom 21 ). A Google nie zapewnia żadnego sposobu, aby ustawić maksymalny poziom powiększenia w tym momencie. Może się to zdarzyć również wtedy, gdy jest więcej niż 1 marker, ale wszyscy są blisko siebie. Wtedy pojawi się również ten sam problem.

Rozwiązanie - Załóżmy, że chcesz, aby Twoja mapa nigdy nie przekraczała poziomu powiększenia 16. Następnie po zrobieniu -

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

Sprawdź, czy twój poziom powiększenia przekroczył poziom 16 (lub cokolwiek chcesz) -

float currentZoom = mMap.getCameraPosition().zoom;

I jeśli ten poziom jest większy niż 16, co będzie tylko wtedy, gdy jest bardzo mniej znaczników lub wszystkie znaczniki są bardzo blisko siebie, po prostu pomniejsz mapę w tym konkretnym miejscu tylko ustawiając poziom powiększenia na 16.

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

W ten sposób nigdy nie będziesz miał problemu z "dziwacznym" poziomem powiększenia wyjaśnionego bardzo dobrze przez @andr.

 5
Author: Jyotman Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:49

To by pomogło.. od google API 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));
                }
            });
        }
    }

Aby uzyskać jasne informacje, spójrz na ten adres url. https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java

 3
Author: Amit Tumkur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-29 11:35:05

Miałem podobny problem, używając poniższego kodu rozwiązałem problem:

CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 5) generalnie różnice w lokalizacji w moim przypadku to nie więcej niż dwa sąsiednie miasta.

Powiększ, aby dopasować wszystkie znaczniki na mapie google maps v2

 1
Author: Avishkar Ramjeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-12 12:17:38

Mam jeszcze jeden sposób, aby zrobić to samo działa idealnie. tak więc idea Za, aby pokazać wszystkie znaczniki na ekranie musimy środek lat długi i poziom powiększenia. oto funkcja, która da ci oba i potrzebuje wszystkich obiektów latlng markera jako danych wejściowych.

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

Ta funkcja zwraca obiekt pary, którego możesz użyć jak

Para Para = getCenterWithZoomLevel (l1, l2,l3..); mGoogleMap.moveCamera (CameraUpdateFactory.newLatLngZoom (para.pierwszy, para.second));

Możesz zamiast używać paddingu, aby trzymać markery z dala od granic ekranu, możesz dostosować powiększenie o -1.

 1
Author: Anuj Jindal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-14 09:18:03

Pokaż wszystkie znaczniki z mapą Google

W tych metodach Przechowuj wszystkie znaczniki i automatycznie powiększaj, aby wyświetlić wszystkie znaczniki na mapie google.

// 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);
}
 1
Author: Sathish kumar T.M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-16 12:15:06

Użyj metody "getCenterCoordinate", aby uzyskać współrzędną Środkową i użyj w kamerze.

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();
}
 0
Author: Jonathan Nolasco Barrientos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-23 19:08:05

Pracowałem nad tym samym problemem przy pokazywaniu wielu znaczników w Kotlinie przy użyciu fragmentu

Najpierw zadeklaruj listę znaczników

private lateinit var markers: MutableList<Marker>

Zainicjalizuj to w metodzie oncreate frament

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
                         ): View? {
    //initialize markers list

    markers = mutableListOf()
   
    return inflater.inflate(R.layout.fragment_driver_map, container, false)
}

Na OnMapReadyCallback Dodaj znaczniki do listy znaczników

private val callback = OnMapReadyCallback { googleMap ->

    map = googleMap

    markers.add(
        map.addMarker(
            MarkerOptions().position(riderLatLng)
                .title("Driver")
                .snippet("Driver")
                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED))))


    markers.add(
        map.addMarker(
            MarkerOptions().position(driverLatLng)
                .title("Driver")
                .snippet("Driver")
                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))))

Wciąż na wywołaniu zwrotnym

//create builder
    val builder = LatLngBounds.builder()

    //loop through the markers list
    for (marker in markers) {

        builder.include(marker.position)
    }
    //create a bound
    val bounds = builder.build()

    //set a 200 pixels padding from the edge of the screen
    val cu = CameraUpdateFactory.newLatLngBounds(bounds,200)
    
    //move and animate the camera
    map.moveCamera(cu)
    //animate camera by providing zoom and duration args, callBack set to null
    map.animateCamera(CameraUpdateFactory.zoomTo(10f), 2000, null)

Merry coding guys

 0
Author: Tonnie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-16 06:03:10
   //For adding a marker in Google map
        MarkerOptions mp = new MarkerOptions();
        mp.position(new LatLng(Double.parseDouble(latitude), Double.parseDouble(longitude)));
        mp.snippet(strAddress);
        map.addMarker(mp);

        try {

            b = new LatLngBounds.Builder();

            if (MapDetailsList.list != null && MapDetailsList.list.size() > 0) {

                for (int i = 0; i < MapDetailsList.list.size(); i++) {

                    b.include(new LatLng(Double.parseDouble(MapDetailsList.list.get(i).getLatitude()),
                            Double.parseDouble(MapDetailsList.list.get(i).getLongitude())));

                }
                LatLngBounds bounds = b.build();

                DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
                int width = displayMetrics.widthPixels;
                int height = displayMetrics.heightPixels;

                // Change the padding as per needed
                CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, width-200, height-200, 5);
                // map.setCenter(bounds.getCenter());

                map.animateCamera(cu);

            }

        } catch (Exception e) {

        }

Http://i64.tinypic.com/2qjybh4.png

Http://i63.tinypic.com/flzwus.png

Http://i63.tinypic.com/112g5fm.png

 -3
Author: PeddiRaju,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-05 12:29:09