Tüm işaretleri göstermek için Android harita v2 zoom


286

İçinde 10 işaretçi var GoogleMap. Mümkün olduğunca yakınlaştırmak ve tüm işaretçileri görmek istiyor musunuz? Önceki sürümde bu elde edilebilir zoomToSpan()ama v2'de bunu nasıl yapacağım hakkında hiçbir fikrim yok. Ayrıca, görünür olması gereken dairenin yarıçapını biliyorum.

Yanıtlar:


810

CameraUpdateSınıfı, tüm programlı harita hareketlerini (muhtemelen) yapmak için kullanmalısınız .

Bunu yapmak için, önce tüm işaretçilerin sınırlarını şu şekilde hesaplayın:

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

Ardından fabrikayı kullanarak bir hareket tanımı nesnesi edinin CameraUpdateFactory:

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

Son olarak haritayı taşıyın:

googleMap.moveCamera(cu);

Veya bir animasyon istiyorsanız:

googleMap.animateCamera(cu);

Bu kadar :)

Açıklama 1

Hemen hemen tüm hareket yöntemleri Mapnesnenin mizanpaj sürecini geçmesini gerektirir . Yapıyı kullanarak bunun olmasını bekleyebilirsiniz addOnGlobalLayoutListener. Ayrıntılar bu yanıtın yorumlarında ve kalan yanıtlarda bulunabilir. Burada kullanarak harita kapsamını ayarlamak için tam bir kodaddOnGlobalLayoutListener da bulabilirsiniz .

Açıklama 2

Bir yorum, bu yöntemi yalnızca bir işaretçi için kullanmanın harita yakınlaştırmasının "tuhaf" yakınlaştırma düzeyine ayarlandığını (belirli bir konum için kullanılabilir maksimum yakınlaştırma düzeyi olduğuna inanıyorum) not eder. Bunun beklendiğini düşünüyorum çünkü:

  1. LatLngBounds boundsÖrnek olacak northeastiçin eşit özellik southwest, bu kapsadığı toprak alanının kısım, yani boundstam olarak sıfırdır. (Tek bir işaretçinin alanı olmadığı için bu mantıklıdır.)
  2. Size geçerek bounds, CameraUpdateFactory.newLatLngBoundsesasen bounds(sıfır alana sahip) tüm harita görünümünü kapsayacak bir yakınlaştırma seviyesinin hesaplanmasını talep edersiniz .
  3. Bu hesaplamayı aslında bir kağıt üzerinde yapabilirsiniz. Yanıtın teorik zoom seviyesi + ∞ (pozitif sonsuzluk) 'dur. Pratikte Mapnesne bu değeri desteklemediğinden, verilen konum için izin verilen daha makul bir maksimum düzeye kenetlenir.

Başka bir deyişle: Mapnesne tek bir konum için hangi zum düzeyini seçmesi gerektiğini nasıl bilebilir ? Belki de optimal değer 20 olmalıdır (belirli bir adresi temsil ediyorsa). Ya da belki 11 (bir kasabayı temsil ediyorsa). Ya da belki 6 (bir ülkeyi temsil ediyorsa). API o kadar akıllı değil ve karar size kalmış.

Bu nedenle, markersyalnızca bir konumun olup olmadığını kontrol etmelisiniz ve eğer öyleyse aşağıdakilerden birini kullanın:

  • CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition()) - işaretleyici konumuna gidin, geçerli zoom seviyesini olduğu gibi bırakın.
  • CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F) - işaretleyici konumuna gidin, zoom seviyesini keyfi olarak seçilen değere ayarlayın 12.

21
Taşıma onCreate çağrılarından gerçekleşemez, görünüm oluşturulmalıdır. Uygun örneği almak için addOnGlobalLayoutListener kullanmam gerekiyordu.
Baruch Hatta

6
@Bar Bu kısmen doğru. Kesin olmak gerekirse: bazı hareket yöntemleri, harita nesnesini oluşturduktan hemen sonra çalışmaz. Bunun nedeni harita nesnesinin henüz ölçülmemiş olması, yani mizanpaj işleminden geçirilmemesidir. Tipik bir düzeltme kullanmak addOnGlobalLayoutListener()veya post()uygun bir yöntemdir Runnable. İşaretleyici ekran koordinatlarını almanın tam olarak nedeni bu değildir onCreate- bkz. Stackoverflow.com/q/14429877/1820695 Bununla birlikte , düzen olmadan önce bazı yöntemleri kullanabilirsiniz - ör. CameraUpdateFactory.newLatLngBounds()ile 4 params .
andr

1
Adamım, sen benim günümü kurtardın ... aslında kendi başıma yapmaya çalışıyordum, elle sınırları hesaplamaya ve işaretçi içinde iken zum yapmaya çalışıyordum ... oldukça çirkin çalışıyordu, ama basit yönteminle bir cazibe gibi çalışıyor. Teşekkürler
Bibu

9
googleMap .setOnMapLoadedCallback (yeni GoogleMap.OnMapLoadedCallback () {@OnMapLoaded () {googleMap.moveCamera (cu);}}); Bu, ölçülen hatayı önleyecektir.
Ramz

1
aksi halde çalışır ancak harita üzerinde tek bir işaretleyici olduğunda, haritanın bulanıklaştığı tuhaf bir seviyeye yakınlaştırır. Bunu nasıl düzeltirim?
Utsav Gupta

124

Google Harita V2

Aşağıdaki çözüm Android Marshmallow 6 için çalışır (API 23, API 24, API 25, API 26, API 27, API 28). Ayrıca Xamarin'de de çalışır.

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

7
Daha iyi görünümlü dolgu için, genişlik yerine yükseklik kullanın ve% 10 yerine% 20 alın.
noob

2
Kabul edilen cevap bazen garip yakınlaştırmaya neden olabilir. Bu bir cazibe gibi çalışır. Bu daha iyi bir cevap.
Hüseyin Bülbül

1
Bu cevap kabul edilenden daha iyi çalışır, kabul edilen cevap bazı garip davranışlara neden olur.
Haytham

13

Yani

Uygun örneği almak için addOnGlobalLayoutListener kullanmam gerekiyordu

örneğin, Google Haritanız RelativeLayout'un içindedir:

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
Buraya Udemy öğreticisinden geldi, harika iş adamı, onlar sorunu çözmek için cevabını kullandılar.
Shantanu Shady

13

Ben onGlobalLayoutlistener kullanamadı, bu yüzden burada "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."hatayı önlemek için başka bir çözüm :

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

Bu seferki hala benim ihtiyaçlarına kamerayı taşımadan önce, ilk / varsayılan bölgeyi Büyütmek haritaları gösterdi benim için çok uzun OnGlobalLayoutListener daha yol alır
Till

Benim 2 işaretçiler harita sınırları ile dokunulur gibi bazı dolgu vermek nasıl.
Pratik Butani

9

Benim için iyi çalışıyor.

Bu koddan, harita ekranında belirli yakınlaştırma ile birden çok işaretçi görüntülüyorum.

// Bildirilen değişkenler

private LatLngBounds bounds;
private LatLngBounds.Builder builder;

// Çekilebilir simgeli birden çok işaretçi noktası ekleme yöntemi

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

    }

// Haritada görünen birden çok işaretçi eklemek için

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

4

Not - Bu orijinal sorunun çözümü değildir. Bu, yukarıda tartışılan alt sorunlardan birine bir çözümdür .

@And Clarification 2 çözümü -

Sınırlarda sadece bir işaretçi olduğunda ve bu yüzden zum seviyesi çok yüksek bir seviyeye ( seviye 21 ) ayarlandığında gerçekten sorunlu . Google, bu noktada maksimum zum düzeyini ayarlamak için herhangi bir yol sunmaz. Bu, 1'den fazla marker olduğunda da olabilir, ancak hepsi birbirine oldukça yakındır. Sonra aynı sorun ortaya çıkacaktır.

Çözüm - Haritanızın asla 16 zum seviyesinin üzerine çıkmasını istemediğinizi varsayalım. Sonra yaptıktan sonra -

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

Zoom seviyenizin seviye 16'yı (veya istediğinizi) geçip geçmediğini kontrol edin -

float currentZoom = mMap.getCameraPosition().zoom;

Ve bu seviye 16'dan büyükse, sadece çok daha az işaretçi varsa veya tüm işaretçiler birbirine çok yakınsa, haritanızı yalnızca o yakınlaştırma seviyesini 16'ya ayarlayarak o konuma getirin.

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

Bu şekilde "tuhaf" zum seviyesi problemi @andr tarafından çok iyi açıklanmayacaktır.


iyi bir çözüm, ancak "cu" nesnesini onMapReady () içine koyarsanız, bu durumda bir yanlış davranış söz konusudur: konum alındı ​​-> zum büyük, bu yüzden 16 -> yapınız - yakınlaştırır -> konum tekrar alınır ve kamera 16. seviyeye geri dönün . Bu, konum 16'ya geri dönmeye devam edeceği için neredeyse gerçek zamanlı olarak alındığında bir sorun olabilir
Maher Nabil

"Ve Google, bu noktada maksimum zum düzeyini ayarlamak için herhangi bir yol sağlamaz." - Doğru değil: developers.google.com/android/reference/com/google/android/gms/…
user1209216

3

bu yardımcı olur .. google apis demolarından

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

net bilgi için bu url'ye bakın. https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java



1

Google işaretli Tüm İşaretçileri Göster

Bu Yöntemlerde tüm İşaretçileri saklayın ve Google haritasındaki tüm işaretçileri göstermek için otomatik olarak yakınlaştırın.

// 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

Merkez koordinatını elde etmek ve CameraPosition'da kullanmak için "getCenterCoordinate" yöntemini kullanın.

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

Aynı şeyi mükemmel bir şekilde yapmak için başka bir yolum var. Ekrandaki tüm işaretleyicileri göstermek için arkadaki fikir, ortadaki bir uzunluğa ve yakınlaştırma seviyesine ihtiyacımız var. İşte size her ikisini de veren ve tüm işaretleyicinin Latlng nesnelerine giriş olarak ihtiyaç duyan işlev.

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

Bu işlev aşağıdaki gibi kullanabileceğiniz Pair nesnesini döndürür

Çift çifti = getCenterWithZoomLevel (l1, l2, l3 ..); mGoogleMap.moveCamera (CameraUpdateFactory.newLatLngZoom (pair.first, pair.second));

işaretlerinizi ekran sınırlarından uzak tutmak için dolgu kullanmak yerine yakınlaştırmayı -1 oranında ayarlayabilirsiniz.


-3
   //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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.