Saya menggunakan API Google Maps Android baru .
Saya membuat aktivitas yang menyertakan MapFragment. Dalam aktivitas, onResume
saya mengatur penanda ke dalam objek GoogleMap dan kemudian menentukan kotak pembatas untuk peta yang mencakup semua penanda.
Ini menggunakan kode semu berikut:
LatLngBounds.Builder builder = new LatLngBounds.Builder();
while(data) {
LatLng latlng = getPosition();
builder.include(latlng);
}
CameraUpdate cameraUpdate = CameraUpdateFactory
.newLatLngBounds(builder.build(), 10);
map.moveCamera(cameraUpdate);
Panggilan tersebut map.moveCamera()
menyebabkan aplikasi saya macet dengan tumpukan berikut:
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)
Jika - alih-alih newLatLngBounds()
metode pabrik, saya menggunakan newLatLngZoom()
metode maka jebakan yang sama tidak terjadi.
Apakah tempat onResume
terbaik untuk menggambar penanda ke objek GoogleMap atau haruskah saya menggambar penanda dan menyetel posisi kamera di tempat lain?
setOnCameraChangeListener
sekarang tidak digunakan lagiJawaban tersebut baik-baik saja, tetapi saya akan menggunakan pendekatan yang berbeda, yang lebih sederhana. Jika metode ini hanya berfungsi setelah peta ditata, tunggu saja:
sumber
OK saya mengerjakan ini. Seperti yang didokumentasikan di sini bahwa API tidak dapat digunakan sebelum tata letak.
API yang benar untuk digunakan dijelaskan sebagai:
Untuk memperbaiki masalah, saya menghitung ukuran layar saya dan memberikan lebar dan tinggi
Ini kemudian memungkinkan saya untuk menentukan tata letak kotak pembatas.
sumber
Solusinya lebih sederhana dari itu ....
Tangkap
IllegalStateException
dan gunakan pendengar global pada tampilan sebagai gantinya. Menetapkan ukuran terikat terlebih dahulu (pra-tata letak) menggunakan metode lain berarti Anda harus menghitung ukuran PANDANGAN, bukan perangkat layar. Mereka hanya cocok jika Anda pergi layar penuh dengan peta Anda dan tidak menggunakan fragmen.sumber
Ini perbaikan saya, tunggu saja sampai peta dimuat dalam kasus itu.
sumber
Menambah dan menghapus penanda dapat dilakukan penyelesaian pra-tata letak, tetapi menggerakkan kamera tidak bisa (kecuali menggunakan
newLatLngBounds(boundary, padding)
seperti yang disebutkan dalam jawaban OP).Mungkin tempat terbaik untuk melakukan pembaruan kamera awal adalah menggunakan satu jepretan
OnGlobalLayoutListener
seperti yang ditunjukkan dalam kode contoh Google , misalnya lihat kutipan berikut darisetUpMap()
di MarkerDemoActivity.java :sumber
Jawaban yang diterima tidak akan berfungsi untuk saya karena saya harus menggunakan kode yang sama di berbagai tempat aplikasi saya.
Alih-alih menunggu kamera berubah, saya membuat solusi sederhana berdasarkan saran Lee untuk menentukan ukuran peta. Ini seandainya peta Anda berukuran layar.
Semoga bisa membantu orang lain!
sumber
Jawaban yang diterima, seperti yang ditunjukkan di komentar, sedikit hacky. Setelah menerapkannya, saya melihat jumlah
IllegalStateException
log di analytics yang dapat diterima di atas. Solusi yang saya gunakan adalah menambahkanOnMapLoadedCallback
di manaCameraUpdate
dilakukan. Callback ditambahkan keGoogleMap
. Setelah peta Anda dimuat sepenuhnya, pembaruan kamera akan dilakukan.Hal ini menyebabkan peta secara singkat menunjukkan tampilan yang diperkecil (0,0) sebelum melakukan pembaruan kamera. Saya merasa ini lebih dapat diterima daripada menyebabkan crash atau mengandalkan perilaku yang tidak terdokumentasi.
sumber
gunakan ini, itu berhasil untukku
sumber
Dalam kasus yang sangat jarang terjadi, tata letak MapView selesai, tetapi tata letak GoogleMap belum selesai,
ViewTreeObserver.OnGlobalLayoutListener
itu sendiri tidak dapat menghentikan kerusakan. Saya melihat crash dengan paket layanan Google Play versi 5084032. Kasus yang jarang terjadi ini mungkin disebabkan oleh perubahan dinamis pada visibilitas MapView saya.Untuk mengatasi masalah ini, saya tertanam
GoogleMap.OnMapLoadedCallback
dionGlobalLayout()
,sumber
mapView.getViewTreeObserver()
menjadi variabel lokal , kesalahan berikut terjadi: "IllegalStateException: ViewTreeObserver ini tidak hidup, panggil getViewTreeObserver () lagi" . Apakah kamu sudah mencobanya?Saya menggunakan pendekatan berbeda yang berfungsi untuk versi terbaru Google Maps SDK (9.6+) dan berdasarkan onCameraIdleListener . Seperti yang saya lihat sejauh ini, metode callback
onCameraIdle
selalu dipanggil setelahonMapReady
. Jadi pendekatan saya terlihat seperti potongan kode ini (mengingatnya dimasukkanActivity
):sumber
Saya telah membuat cara untuk menggabungkan dua callback: onMapReady dan onGlobalLayout menjadi satu observable tunggal yang akan memancarkan hanya ketika kedua peristiwa telah dipicu.
https://gist.github.com/abhaysood/e275b3d0937f297980d14b439a8e0d4a
sumber
Oke, saya menghadapi masalah yang sama. Saya memiliki fragmen saya dengan SupportmapFragment, ABS, dan laci navigasi saya. Apa yang saya lakukan adalah:
Dan, omong-omong, saya menelepon
resetCamera()
darionCreateView
setelah menggembungkan dan sebelum kembali.Apa yang dilakukan ini adalah menangkap pengecualian pertama kali (sementara peta "mendapat ukuran" sebagai cara untuk mengatakannya ...) dan kemudian, di lain waktu saya perlu mengatur ulang kamera, peta sudah memiliki ukuran dan melakukannya melalui bantalan.
Masalah dijelaskan dalam dokumentasi , dikatakan:
Saya pikir ini solusi yang cukup baik. Semoga bisa membantu seseorang.
sumber
newLatLngBounds()
atau dianimateCamera()
, atau di keduanya? Apakah cabang penangkap tidak akan menghasilkan pengecualian baru?Jika Anda perlu menunggu kemungkinan interaksi pengguna untuk dimulai, gunakan
OnMapLoadedCallback
seperti yang dijelaskan dalam jawaban sebelumnya. Namun, jika yang Anda butuhkan hanyalah memberikan lokasi default untuk peta, tidak perlu solusi apa pun yang diuraikan dalam jawaban tersebut. KeduanyaMapFragment
danMapView
dapat menerimaGoogleMapOptions
di awal yang dapat memberikan lokasi default dengan baik. Trik satu-satunya adalah dengan tidak menyertakannya secara langsung dalam tata letak Anda karena sistem akan memanggilnya tanpa opsi, tetapi menginisialisasinya secara dinamis.Gunakan ini dalam tata letak Anda:
dan ganti fragmen di
onCreateView()
:Selain lebih cepat untuk memulai, tidak akan ada peta dunia yang ditampilkan pertama dan kamera bergerak kedua. Peta akan langsung dimulai dengan lokasi yang ditentukan.
sumber
Pendekatan lain akan seperti ini (Dengan asumsi tampilan teratas Anda adalah FrameLayout bernama
rootContainer
, meskipun itu akan berfungsi selama Anda selalu memilih penampung teratas Anda tidak peduli jenis atau nama yang dimilikinya):Memodifikasi fungsi kamera Anda agar hanya berfungsi jika
layoutDone
adatrue
akan menyelesaikan semua masalah Anda tanpa harus menambahkan fungsi tambahan atau menghubungkan logika kelayoutListener
pawang.sumber
Saya menemukan ini berfungsi dan menjadi lebih sederhana daripada solusi lain:
Ini mencoba panggilan lagi setelah layout dijalankan. Mungkin bisa termasuk pengaman untuk menghindari loop tak terbatas.
sumber
Mengapa tidak menggunakan sesuatu seperti ini:
sumber
newLatLngBounds(builder.build(), padding)
tidak di dalam coba-tangkap? Apakah pengecualian ini terjadi dimoveCamera()
?Ada kelas pembantu di repo Google Maps yang dapat Anda manfaatkan - kelas itu menunggu tata letak dan peta siap sebelum memberi tahu panggilan balik dengan GoogleMap:
Sumber aslinya ada di sini:
https://github.com/googlemaps/android-samples/blob/7ee737b8fd6d39c77f8b3716ba948e1ce3730e61/ApiDemos/java/app/src/main/java/com/example/mapdemo/OnMapAndViewReadyListener.java
Ada juga implementasi Kotlin:
https://github.com/googlemaps/android-samples/blob/master/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/OnMapAndViewReadyListener.kt
sumber
Seperti yang dinyatakan di OnCameraChangeListener () tidak digunakan lagi ,
setOnCameraChangeListener
sekarang tidak digunakan lagi. Jadi, Anda harus menggantinya dengan salah satu dari tiga mode:GoogleMap.OnCameraMoveStartedListener
GoogleMap.OnCameraMoveListener
GoogleMap.OnCameraIdleListener
Dalam kasus saya, saya menggunakan
OnCameraIdleListener
dan di dalam saya menghapusnya karena itu dipanggil lagi dan lagi pada setiap gerakan.MEMPERBARUI
Saya menghapus
googleMap.setOnCameraIdleListener
dalam proyek saya, karena kadang-kadang tidak dipanggil ketika peta ditampilkan, tetapi dipertahankangoogleMap.setOnCameraIdleListener(clusterManager)
.sumber
Saya mengalami kesalahan yang sama saat mencoba memanggil mMap.animateCamera. Saya menyelesaikannya dengan memanggil callback setOnMapLoadedCallback dalam fungsi onMapReady saya seperti yang ditunjukkan di bawah ini
Ini seharusnya bekerja dengan baik.
sumber