Я использую новый Android Google Maps API .
Я создаю действие, которое включает MapFragment. В этом упражнении onResume
я устанавливаю маркеры в объект GoogleMap, а затем определяю ограничивающую рамку для карты, которая включает все маркеры.
Это использует следующий псевдокод:
LatLngBounds.Builder builder = new LatLngBounds.Builder();
while(data) {
LatLng latlng = getPosition();
builder.include(latlng);
}
CameraUpdate cameraUpdate = CameraUpdateFactory
.newLatLngBounds(builder.build(), 10);
map.moveCamera(cameraUpdate);
Вызов map.moveCamera()
вызывает сбой моего приложения со следующим стеком:
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)
Если - вместо newLatLngBounds()
фабричного метода я использую newLatLngZoom()
метод, то такой ловушки не возникает.
Является ли onResume
лучшее место , чтобы сделать маркеры на объект GoogleMap или я должен быть рисунок маркеры и настройки положения камеры где - нибудь еще?
setOnCameraChangeListener
устарелоЭти ответы прекрасны, но я бы выбрал другой подход, более простой. Если метод работает только после того, как карта выложена, просто подождите:
источник
Хорошо, я разобрался с этим. Как описано здесь , API нельзя использовать перед макетом.
Правильный API для использования описывается как:
Чтобы решить эту проблему, я рассчитал размер экрана и указал ширину и высоту для
Это позволило мне указать предварительный макет ограничивающей рамки.
источник
Решение проще ...
Поймайте
IllegalStateException
и используйте вместо этого глобальный слушатель в представлении. Предварительная установка размера границы (предварительная компоновка) с использованием других методов означает, что вам нужно вычислить размер ВИДА, а не устройства экрана. Они совпадают только в том случае, если вы используете карту в полноэкранном режиме и не используете фрагменты.источник
Это мое исправление, просто подождите, пока карта загрузится в этом случае.
источник
Добавление и удаление маркеров может быть выполнено до завершения макета, но перемещение камеры невозможно (за исключением использования
newLatLngBounds(boundary, padding)
как указано в ответе OP).Вероятно, лучшее место для выполнения первоначального обновления камеры - использовать однократный снимок,
OnGlobalLayoutListener
как показано на примере кода от Google , например , см следующего отрывка изsetUpMap()
в MarkerDemoActivity.java :источник
Принятый ответ не сработает для меня, потому что мне пришлось использовать один и тот же код в разных местах моего приложения.
Вместо того, чтобы ждать смены камеры, я создал простое решение, основанное на предложении Ли указать размер карты. Это на случай, если ваша карта размером с экран.
Надеюсь, это поможет кому-то другому!
источник
Принятый ответ, как указано в комментариях, немного взломан. После внедрения заметил
IllegalStateException
в аналитике недопустимое количество логов. Решение, которое я использовал, - это добавить объект,OnMapLoadedCallback
в которомCameraUpdate
выполняется. Обратный вызов добавлен вGoogleMap
. После полной загрузки карты будет выполнено обновление камеры.Это заставляет карту ненадолго показывать уменьшенное изображение (0,0) перед выполнением обновления камеры. Я считаю, что это более приемлемо, чем вызывать сбои или полагаться на недокументированное поведение.
источник
использовать это сработало для меня
источник
В очень редких случаях макет MapView завершен, но макет GoogleMap не завершен,
ViewTreeObserver.OnGlobalLayoutListener
сам по себе не может остановить сбой. Я видел сбой в пакете сервисов Google Play версии 5084032. Этот редкий случай может быть вызван динамическим изменением видимости моего MapView.Чтобы решить эту проблему, я встроил
GoogleMap.OnMapLoadedCallback
вonGlobalLayout()
,источник
mapView.getViewTreeObserver()
в локальную переменную следующие ошибки происходит: «IllegalStateException: Это ViewTreeObserver нет в живых, называют getViewTreeObserver () еще раз» . Вы пробовали это?Я использовал другой подход, который работает для последних версий Google Maps SDK (9.6+) и основан на onCameraIdleListener . Насколько я понимаю, этот метод обратного вызова
onCameraIdle
всегда вызывается послеonMapReady
. Итак, мой подход выглядит как этот фрагмент кода (учитывая его вставкуActivity
):источник
Я создал способ объединить два обратных вызова: onMapReady и onGlobalLayout в один наблюдаемый объект, который будет генерировать только тогда, когда оба события будут запущены.
https://gist.github.com/abhaysood/e275b3d0937f297980d14b439a8e0d4a
источник
Хорошо, у меня такая же проблема. У меня есть фрагмент с моим SupportmapFragment, ABS и навигационным ящиком. Что я сделал:
И, кстати, звоню
resetCamera()
из-onCreateView
за накачки и перед возвращением.То, что это делает, - это первый раз перехватить исключение (в то время как карта «получает размер» как способ сказать это ...), а затем, в других случаях, когда мне нужно сбросить камеру, карта уже имеет размер и делает это через заполнение.
Проблема объясняется в документации , в ней говорится:
Думаю, это довольно приличное решение. Надеюсь, это кому-то поможет.
источник
newLatLngBounds()
или вanimateCamera()
, или в обоих? Не приведет ли перехватчик к новому исключению?Если вам нужно дождаться начала возможного взаимодействия с пользователем, используйте,
OnMapLoadedCallback
как описано в предыдущих ответах. Но если все, что вам нужно, это указать местоположение по умолчанию для карты, нет необходимости в каких-либо решениях, изложенных в этих ответах. ОбаMapFragment
иMapView
могут принятьGoogleMapOptions
при запуске, что может правильно указать местоположение по умолчанию. Единственная уловка - не включать их непосредственно в ваш макет, потому что тогда система будет вызывать их без параметров, а инициализировать их динамически.Используйте это в своем макете:
и замените фрагмент в своем
onCreateView()
:Помимо более быстрого запуска, сначала не будет отображаться карта мира, а во вторую - движение камеры. Карта начнется напрямую с указанного места.
источник
Другой подход может выглядеть примерно так (при условии, что ваше самое верхнее представление - это FrameLayout с именем
rootContainer
, даже если оно будет работать, пока вы всегда выбираете свой самый верхний контейнер, независимо от того, какой у него тип или имя):Изменение функций камеры так, чтобы они работали только в том случае, если
layoutDone
этоtrue
решит все ваши проблемы без добавления дополнительных функций или подключения логики кlayoutListener
обработчику.источник
Я обнаружил, что это работает и проще, чем другие решения:
Это пытается выполнить вызов еще раз после запуска макета. Возможно, можно было бы включить безопасность, чтобы избежать бесконечного цикла.
источник
Почему бы просто не использовать что-то вроде этого:
источник
newLatLngBounds(builder.build(), padding)
нет внутри try-catch? Возникает ли это исключение вmoveCamera()
?В репозитории Google Maps есть вспомогательный класс, который вы можете использовать - он ждет, пока макет и карта будут готовы, прежде чем уведомить обратный вызов с помощью GoogleMap:
Первоисточник здесь:
https://github.com/googlemaps/android-samples/blob/7ee737b8fd6d39c77f8b3716ba948e1ce3730e61/ApiDemos/java/app/src/main/java/com/example/mapdemo/OnMapAndViewReadyListener.
Также есть реализация Kotlin:
https://github.com/googlemaps/android-samples/blob/master/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/OnMapAndViewReadyListener.kt
источник
Как указано в OnCameraChangeListener () устарел ,
setOnCameraChangeListener
теперь он устарел. Поэтому вам следует заменить его одним из трех способов:GoogleMap.OnCameraMoveStartedListener
GoogleMap.OnCameraMoveListener
GoogleMap.OnCameraIdleListener
В моем случае я использовал,
OnCameraIdleListener
а внутри я удалил его, потому что он снова и снова вызывается при любом движении.ОБНОВИТЬ
Я удалил
googleMap.setOnCameraIdleListener
в своем проекте, потому что он иногда не вызывался при показе карты, но сохранялсяgoogleMap.setOnCameraIdleListener(clusterManager)
.источник
У меня была такая же ошибка при попытке вызвать mMap.animateCamera. Я решил это, вызвав обратный вызов setOnMapLoadedCallback в моей функции onMapReady, как показано ниже.
Это должно работать нормально.
источник