CameraUpdateFactory.newLatLngBounds ile moveCamera çöküyor


96

Yeni Android Google Haritalar API'sinden yararlanıyorum .

MapFragment içeren bir aktivite oluşturuyorum. Aktivitede onResume, işaretçileri GoogleMap nesnesine yerleştiriyorum ve ardından tüm işaretleyicileri içeren harita için bir sınırlayıcı kutu tanımlıyorum.

Bu, aşağıdaki sözde kodu kullanıyor:

LatLngBounds.Builder builder = new LatLngBounds.Builder();
while(data) {
   LatLng latlng = getPosition();
   builder.include(latlng);
}
CameraUpdate cameraUpdate = CameraUpdateFactory
   .newLatLngBounds(builder.build(), 10);
map.moveCamera(cameraUpdate);

Çağrı, map.moveCamera()uygulamamın aşağıdaki yığınla çökmesine neden oluyor:

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)

Eğer - newLatLngBounds()fabrika yöntemi yerine yöntemi kullanırsam newLatLngZoom(), aynı tuzak oluşmaz.

onResumeİşaretçileri GoogleMap nesnesine çizmek için en iyi yer mi yoksa işaretçileri çizip kamera konumunu başka bir yere mi ayarlamalıyım?

Yanıtlar:


133

Basit kullanabilirsiniz newLatLngBounds yöntemi OnCameraChangeListener . Hepsi mükemmel şekilde çalışacak ve ekran boyutunu hesaplamanıza gerek kalmayacak. Bu olay harita boyutu hesaplamasından sonra meydana geliyor (anladığım kadarıyla).

Misal:

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

1
Bu işe yarıyor çünkü setOnCameraChangeListener, Harita düzene girdikten sonra en az bir kez çalışacak mı? Bu geleceğin kanıtı mı?
Glenn Bech

3
@SteelRat Bu yüzden çözümü kullanmaya karşı olacağım. Google'ın bunu ne zaman değiştirdiğini veya tüm android sürümlerinde veya cihazlarda bu şekilde çalışıp çalışmadığını asla bilemezsiniz.
Glenn Bech

1
@SteelRat Kabul ediyorum, ancak etkinlik süresince birden fazla kez çağrılabilir mi? Sadece bu durumda işe yarasa bile, çok zarif bir çözüm olmadığını iddia ediyorum. OnGlobalLayoutListener / Treelistener'ın bunu yapmanın daha doğru bir yolu olduğunu düşünüyorum.
Glenn Bech

4
belki map.moveCamera (CameraUpdateFactory.scrollBy (1, 1)) ekleniyor; Yukarıdaki koddan sonra hile yapacak mı?
MY

3
setOnCameraChangeListenerartık kullanımdan kaldırıldı
osrl

56

Bu cevaplar gayet iyi, ama ben daha basit, farklı bir yaklaşıma gidebilirim. Yöntem yalnızca harita yerleştirildikten sonra işe yarıyorsa, bekleyin:

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

1
Birçok deneyden sonra , bu cevabın ve Daniele'nin yukarısının bir kombinasyonunu uygulamaya ihtiyacım olduğunu anladım . Bazen harita henüz yüklenmemişti, bazen yerleşim planı henüz tamamlanmamıştı. Bunların İKİSİ olana kadar kamerayı istediğim gibi hareket ettiremedim.
RobP

2
Dokümanlardan bu yöntem için uyarı: "Bağlantı sorunları nedeniyle harita hiçbir zaman yüklenmezse veya harita sürekli değişiyor ve kullanıcı sürekli olarak haritayla etkileşimde bulunduğu için yüklemeyi hiçbir zaman tamamlamıyorsa bu olay tetiklenmeyecektir ." (vurgu benim).
stkent

1
Bu, gerekenden daha uzun süre geciktirir çünkü doğru konuma geçmeden önce harita döşemelerinin yanlış konumda yüklenmesini bekler.
John Patterson

1
Çoğu zaman, kabul edilemez olan ateş etmek 3-10 saniye arasında bir şey alır.
Nima G

Burası kamerayı hareket ettirecek yer. Map.moveCamera yerine map.animateCamera kullanmanızı öneririm
Bharat Dodeja

51

Tamam bunu hallettim. Burada belgelendiği gibi , API ön düzen olarak kullanılamaz.

Kullanılacak doğru API şu şekilde tanımlanır:

Not: Harita düzenlendikten sonra kamerayı hareket ettirmek için kullanılacaksa CameraUpdate oluşturmak için yalnızca daha basit olan newLatLngBounds (sınır, dolgu) yöntemini kullanın. Yerleşim sırasında API, sınırlayıcı kutuyu doğru bir şekilde yansıtmak için gereken haritanın görüntü sınırlarını hesaplar. Buna karşılık, daha karmaşık yöntem olan newLatLngBounds (sınır, genişlik, yükseklik, dolgu) tarafından döndürülen CameraUpdate'i istediğiniz zaman, hatta harita mizanpajdan önce bile kullanabilirsiniz, çünkü API, geçirdiğiniz argümanlardan görüntüleme sınırlarını hesaplar.

Sorunu çözmek için ekran boyutumu hesapladım ve genişlik ve yüksekliği sağladım

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

Bu, daha sonra sınırlayıcı kutu ön düzenini belirlememe izin verdi.


18
Peki ya harita tüm ekranı kaplamazsa?
theblang

Benim durumumda, gerçekte olduğundan daha büyük bir ekran varsaymıştım ve dolguyu daha dikkatli hesaplamam gerekiyordu, bu yüzden aslında çok büyük değildi . Çok daha basit bir sebep.
rfay

2
Ekran boyutuna göre nasıl hesaplanacağını gösterebilir misin?
Daniel Gomez Rico

Bu çarpışmaz ancak kullanılacak genişlik ve yükseklik saf tahminlere yakın, çizilecek kesin alan gerçekten tahmin edilemez.
Vince

34

Çözüm bundan daha basit ...

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

IllegalStateExceptionBunun yerine görünümdeki genel dinleyiciyi yakalayın ve kullanın. Diğer yöntemleri kullanarak cilt boyutunu önceden ayarlamak (ön yerleşim), ekran cihazının değil, GÖRÜNÜM'ün boyutunu hesaplamanız gerektiği anlamına gelir. Yalnızca haritanızla tam ekrana geçerseniz ve parçalar kullanmazsanız eşleşirler.


Şimdiye kadar küçük pasajınızı kullanıyordum, ancak hala başarısız oluyor ... Doğru cevap ilk cevap :-)
cesards

1
Nasıl / ne zaman başarısız olur? bununla hiç sorun yaşamadım. İlk yanıt, yedek olarak ona sabit kodlanmış bir boyut aktarır. "Artık çökmez" gibi "çalışıyor" ama aynı şeyi yapmıyor.
Daniele Segato

@ andrea.spot Neden daha basit dediğimi hatırlamıyorum. Sanırım kabul edilen çözüm bu arada düzenlendi. Geçerli kabul çözüm harita her zaman doğru değildir bütün ekranı almak varsayalım. Bu duruma düşmezseniz ya haritanın boyutunu bilmeniz ya da benim yöntemimi ya da benzer bir şeyi kullanmanız gerekir.
Daniele Segato

Xingang Huang'ın aşağıdaki cevabını da kontrol edin, biraz daha ekler.
Daniele Segato

15

Bu benim düzeltmem, bu durumda harita yüklenene kadar bekleyin.

final int padding = getResources().getDimensionPixelSize(R.dimen.spacing);    

try {
    mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(pCameraBounds, padding));
} catch (IllegalStateException ise) {

    mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {

        @Override
        public void onMapLoaded() {
            mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(pCameraBounds, padding));
        }
    });
}

Basit ve etkili +1
Shid

14

İşaretçilerin eklenmesi ve kaldırılması, yerleşim öncesi tamamlama yapılabilir, ancak kamerayı hareket ettiremez ( newLatLngBounds(boundary, padding)OP'nin cevabında belirtildiği gibi kullanmak dışında ).

Muhtemelen bir başlangıç kamera güncellemesini gerçekleştirmek için en iyi yer tek atış kullanıyor OnGlobalLayoutListenergösterildiği gibi Google'ın örnek kod mesela şu parçayı bakın setUpMap()yılında 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));
        }
    });
}


Oryantasyon değişikliğinde bu hatayı alıyorum. Bunu örnek koddan da buldum ama bu benim için işe yaramadı. Ben hala aynı hatayı alıyorum.
osrl

14

Kabul edilen yanıt benim için işe yaramazdı çünkü aynı kodu uygulamamın çeşitli yerlerinde kullanmak zorundaydım.

Kameranın değişmesini beklemek yerine, Lee'nin harita boyutunu belirleme önerisine dayanarak basit bir çözüm geliştirdim. Bu, haritanızın ekran boyutunda olması durumunda geçerlidir.

// Gets screen size
int width = getResources().getDisplayMetrics().widthPixels;
int height = getResources().getDisplayMetrics().heightPixels;
// Calls moveCamera passing screen size as parameters
map.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), width, height, 10));

Umarım başkasına yardımcı olur!


8

Kabul edilen cevap, yorumlarda da belirtildiği gibi biraz karmaşık. Bunu uyguladıktan sonra IllegalStateException, analitikte kabul edilebilir miktarda günlük kaydı fark ettim . Kullandığım çözüm OnMapLoadedCallback, CameraUpdateiçinde gerçekleştirildiği bir eklemektir . Geri arama GoogleMap,. Haritanız tamamen yüklendikten sonra kamera güncellemesi gerçekleştirilecektir.

Bu, haritanın, kamera güncellemesi yapmadan önce kısaca uzaklaştırılmış (0,0) görünümü göstermesine neden olur. Bunun çökmelere neden olmaktan veya belgelenmemiş davranışlara güvenmekten daha kabul edilebilir olduğunu düşünüyorum.


5
 map.moveCamera(CameraUpdateFactory.newLatLngZoom(bounds.getCenter(),10));

bunu kullan benim için çalıştı


Bu yalnızca haritayı ortalar, ancak yakınlaştırmayı sınırlara göre dinamik olarak ayarlamaz.
shaithana

Daha fazla konu için sınırları "LatLngBounds.Builder" kullanarak hesaplayabiliriz.
Ramesh Bhupathi

@RameshBhupathi, ancak yine de merkezi ve yakınlaştırma içeren bir harita görünümü olarak kalacak.
Tima

4

Çok nadir durumlarda, MapView düzeni bitmiştir, ancak GoogleMap düzeni tamamlanmamıştır, çökmeyi ViewTreeObserver.OnGlobalLayoutListenerdurduramaz. Google Play hizmetleri paketi sürüm 5084032'de çökme gördüm. Bu nadir durum, MapView'umun görünürlüğünün dinamik değişikliğinden kaynaklanıyor olabilir.

Bu sorunu çözmek için, ben gömülü GoogleMap.OnMapLoadedCallbackiçinde onGlobalLayout(),

if (mapView.getViewTreeObserver().isAlive()) {
    mapView.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        @SuppressWarnings("deprecation")
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } else {
                mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
            try {
                map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 5));
            } catch (IllegalStateException e) {
                map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
                    @Override
                    public void onMapLoaded() {
                        Log.d(LOG_TAG, "move map camera OnMapLoadedCallback");
                        map.moveCamera(CameraUpdateFactory
                            .newLatLngBounds(bounds, 5));
                    }
                });
            }
        }
    });
}

İlginç: Yerel bir değişkene yeniden mapView.getViewTreeObserver()düzenleme yaparsam şu hata oluşur: "IllegalStateException: Bu ViewTreeObserver canlı değil, getViewTreeObserver () 'ı tekrar çağırın" . Bunu denedin mi
JJD

. MapView.getViewTreeObserver () isalive () yanlış olduğu gerçekleşmesi ise ben map.setOnMapLoadedCallback () için daha geri dönüş tane koyardım
southerton

4

Google Haritalar SDK'sının (9.6+) son sürümleri için çalışan ve onCameraIdleListener'ı temel alan farklı bir yaklaşım kullandım . Şimdiye kadar gördüğüm gibi onCameraIdleher zaman sonra çağrılan geri arama yöntemi onMapReady. Yaklaşımım şu kod parçasına benziyor (yerleştirildiği düşünüldüğünde Activity):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // set content view and call getMapAsync() on MapFragment
}

@Override
public void onMapReady(GoogleMap googleMap) {
    map = googleMap;
    map.setOnCameraIdleListener(this);
    // other initialization stuff
}

@Override
public void onCameraIdle() {
    /* 
       Here camera is ready and you can operate with it. 
       you can use 2 approaches here:

      1. Update the map with data you need to display and then set
         map.setOnCameraIdleListener(null) to ensure that further events
         will not call unnecessary callback again.

      2. Use local boolean variable which indicates that content on map
         should be updated
    */
}


2

Tamam aynı sorunla karşılaşıyorum. SupportmapFragment, ABS ve gezinti çekmecemle parçam var. Yaptığım şey şuydu:

public void resetCamera() {

    LatLngBounds.Builder builderOfBounds = new LatLngBounds.Builder();
    // Set boundaries ...
    LatLngBounds bounds = builderOfBounds.build();
    CameraUpdate cu;
    try{
        cu = CameraUpdateFactory.newLatLngBounds(bounds,10);
        // This line will cause the exception first times 
        // when map is still not "inflated"
        map.animateCamera(cu); 
        System.out.println("Set with padding");
    } catch(IllegalStateException e) {
        e.printStackTrace();
        cu = CameraUpdateFactory.newLatLngBounds(bounds,400,400,0);
        map.animateCamera(cu);
        System.out.println("Set with wh");
    }

    //do the rest...
}

Ve bu arada, ben çağırıyorum resetCamera()gelen onCreateViewşişirme sonra ve dönmeden önce.
Bunun yaptığı şey ilk seferde istisnayı yakalamaktır (harita bunu söylemenin bir yolu olarak "bir boyut alırken") ve sonra, diğer zamanlarda kamerayı sıfırlamam gerekiyor, haritanın zaten boyutu var ve bunu doldurma yoluyla yapıyor.

Sorun belgelerde açıklanıyor , diyor ki:

Harita düzenine geçene kadar bu kamera güncellemesiyle kamerayı değiştirmeyin (bu yöntemin uygun sınırlayıcı kutuyu ve yakınlaştırma seviyesini doğru şekilde belirlemesi için haritanın bir boyutu olmalıdır). Aksi takdirde bir IllegalStateExceptionatılır. Haritanın kullanılabilir olması yeterli DEĞİLDİR (yani getMap()boş olmayan bir nesne döndürür); haritayı içeren görünüm de boyutları belirlenecek şekilde düzenlenmiş olmalıdır. Bunun gerçekleştiğinden emin değilseniz, newLatLngBounds(LatLngBounds, int, int, int)bunun yerine kullanın ve haritanın boyutlarını manuel olarak sağlayın.

Bence bu oldukça iyi bir çözüm. Umarım birine yardımcı olur.


1
düzen tam olarak yüklendiğinde dinleyecek herhangi bir dinleyici var mı? ?
Sagar Nayak

İstisna büyüdü mı newLatLngBounds()veya animateCamera(), ya da her ikisi de? Yakalama dalı yeni bir istisnaya yol açmayacak mı?
CoolMind

1

Olası kullanıcı etkileşimlerinin başlamasını beklemeniz gerekiyorsa OnMapLoadedCallback, önceki yanıtlarda açıklandığı gibi kullanın . Ancak, ihtiyacınız olan tek şey harita için varsayılan bir konum sağlamaksa, bu yanıtlarda ana hatlarıyla belirtilen çözümlerin hiçbirine gerek yoktur. Her ikisi de MapFragmentve varsayılan konumu tamamen sağlayabilen MapViewbir GoogleMapOptionsbaşlangıçta kabul edebilir. Tek numara, onları doğrudan mizanpajınıza dahil etmemek, çünkü sistem onları seçenekler olmadan arayacak, ancak dinamik olarak başlatacak.

Bunu düzeninizde kullanın:

<FrameLayout
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

ve içindeki parçayı değiştirin onCreateView():

GoogleMapOptions options = new GoogleMapOptions();
options.camera(new CameraPosition.Builder().target(location).zoom(15).build());
// other options calls if required

SupportMapFragment fragment = (SupportMapFragment) getFragmentManager().findFragmentById(R.id.map);
if (fragment == null) {
  FragmentTransaction transaction = getFragmentManager().beginTransaction();
  fragment = SupportMapFragment.newInstance(options);
  transaction.replace(R.id.map, fragment).commit();
  getFragmentManager().executePendingTransactions();
}
if (fragment != null)
  GoogleMap map = fragment.getMap();

Başlamanın daha hızlı olmasının yanı sıra, ilk olarak gösterilen bir dünya haritası ve ikinci olarak bir kamera hareketi olmayacak. Harita, doğrudan belirtilen konumla başlayacaktır.


0

Başka bir yaklaşım, (En üstteki görünümünüzün adlandırılmış bir FrameLayout olduğunu varsayarsak, rootContainerhangi türe veya ada sahip olursa olsun her zaman en üstteki kapsayıcınızı seçtiğiniz sürece çalışacaktır):

((FrameLayout)findViewById(R.id.rootContainer)).getViewTreeObserver()
    .addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        public void onGlobalLayout() {
            layoutDone = true;
        }
    });

Eğer sadece çalışmak için kamera fonksiyonlarını değiştirme layoutDoneisimli trueekstra fonksiyonlar eklemek veya mantık kadar Tel zorunda kalmadan tüm sorunları çözecektir layoutListenerişleyicisi.


0

Bunun işe yaradığını ve diğer çözümlerden daha basit olduğunu buldum:

private void moveMapToBounds(final CameraUpdate update) {
    try {
        if (movedMap) {
            // Move map smoothly from the current position.
            map.animateCamera(update);
        } else {
            // Move the map immediately to the starting position.
            map.moveCamera(update);
            movedMap = true;
        }
    } catch (IllegalStateException e) {
        // Map may not be laid out yet.
        getWindow().getDecorView().post(new Runnable() {
            @Override
            public void run() {
                moveMapToBounds(update);
            }
        });
    }
}

Bu, düzen çalıştıktan sonra aramayı tekrar dener. Sonsuz bir döngüden kaçınmak için muhtemelen bir güvenlik içerebilir.


0

Neden böyle bir şey kullanmıyorsunuz:

CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(builder.build(), padding);
try {
    map.moveCamera(cameraUpdate);
} catch (Exception e) {
    int width = getResources().getDisplayMetrics().widthPixels;
    int height = getResources().getDisplayMetrics().heightPixels;
    cameraUpdate = CameraUpdateFactory.newLatLngBounds(builder.build(), width, height, padding);
    map.moveCamera(cameraUpdate);
}

Neden newLatLngBounds(builder.build(), padding)try-catch içinde değil? Bu istisna ortaya çıkıyor moveCamera()mu?
CoolMind

0

Google Haritalar deposunda yararlanabileceğiniz bir yardımcı sınıf vardır - GoogleMap ile bir geri arama bildiriminde bulunmadan önce hem düzen hem de haritanın hazır olmasını bekler:

Orijinal kaynak burada:

https://github.com/googlemaps/android-samples/blob/7ee737b8fd6d39c77f8b3716ba948e1ce3730e61/ApiDemos/java/app/src/main/java/com/example/mapdemo/OnMapAndViewReadyListener.java

Bir Kotlin uygulaması da var:

https://github.com/googlemaps/android-samples/blob/master/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/OnMapAndViewReadyListener.kt

public class OnMapAndViewReadyListener implements OnGlobalLayoutListener, OnMapReadyCallback {

/** A listener that needs to wait for both the GoogleMap and the View to be initialized. */
public interface OnGlobalLayoutAndMapReadyListener {
    void onMapReady(GoogleMap googleMap);
}

private final SupportMapFragment mapFragment;
private final View mapView;
private final OnGlobalLayoutAndMapReadyListener devCallback;

private boolean isViewReady;
private boolean isMapReady;
private GoogleMap googleMap;

public OnMapAndViewReadyListener(
        SupportMapFragment mapFragment, OnGlobalLayoutAndMapReadyListener devCallback) {
    this.mapFragment = mapFragment;
    mapView = mapFragment.getView();
    this.devCallback = devCallback;
    isViewReady = false;
    isMapReady = false;
    googleMap = null;

    registerListeners();
}

private void registerListeners() {
    // View layout.
    if ((mapView.getWidth() != 0) && (mapView.getHeight() != 0)) {
        // View has already completed layout.
        isViewReady = true;
    } else {
        // Map has not undergone layout, register a View observer.
        mapView.getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    // GoogleMap. Note if the GoogleMap is already ready it will still fire the callback later.
    mapFragment.getMapAsync(this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
    // NOTE: The GoogleMap API specifies the listener is removed just prior to invocation.
    this.googleMap = googleMap;
    isMapReady = true;
    fireCallbackIfReady();
}

@SuppressWarnings("deprecation")  // We use the new method when supported
@SuppressLint("NewApi")  // We check which build version we are using.
@Override
public void onGlobalLayout() {
    // Remove our listener.
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
        mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    } else {
        mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
    isViewReady = true;
    fireCallbackIfReady();
}

private void fireCallbackIfReady() {
    if (isViewReady && isMapReady) {
        devCallback.onMapReady(googleMap);
    }
}
}

0

OnCameraChangeListener () 'de belirtildiği gibi kullanımdan kaldırılmıştır , setOnCameraChangeListenerartık kullanımdan kaldırılmıştır. Yani onu üç mtehod'dan biriyle değiştirmelisiniz:

  • GoogleMap.OnCameraMoveStartedListener
  • GoogleMap.OnCameraMoveListener
  • GoogleMap.OnCameraIdleListener

Benim durumumda kullandım OnCameraIdleListenerve içini çıkardım çünkü herhangi bir harekette tekrar tekrar çağrıldı.

googleMap.setOnCameraIdleListener {
    googleMap.setOnCameraIdleListener(null) // It removes the listener.
    googleMap.moveCamera(track)
    googleMap.cameraPosition
    clusterManager!!.cluster()
    // Add another listener to make ClusterManager correctly zoom clusters and markers.
    googleMap.setOnCameraIdleListener(clusterManager)
}

GÜNCELLEME

Projemden kaldırdım googleMap.setOnCameraIdleListener, çünkü bazen bir harita gösterilirken çağrılmıyordu, ama alıkonuldu googleMap.setOnCameraIdleListener(clusterManager).


Cevabınız için teşekkürler.Çözümün neredeyse aynısını zaten buluyorum.
Arslan Maqbool

@ArslanMaqbool, teşekkürler! Şu anda işlem yapıyorum ve varyantınızı paylaşırsanız size minnettar olacağım.
CoolMind

Memnuniyetle @CoolMind
Arslan Maqbool

0

MMap.animateCamera'yı çağırmaya çalışırken aynı hatayı aldım. Aşağıda gösterildiği gibi onMapReady işlevimde setOnMapLoadedCallback geri aramasını çağırarak çözdüm

public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

   // other codes go there

    mMap.setOnMapLoadedCallback(() -> {
            //Your code where exception occurs goes here...
            
        });
}

Bu iyi çalışmalı.

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.