moveCamera з CameraUpdateFactory.newLatLngBounds аварійно завершує роботу


96

Я використовую новий API Google Maps для Android .

Я створюю діяльність, яка включає 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 чи я повинен малювати маркери та встановлювати положення камери в іншому місці?

Відповіді:


133

Ви можете використовувати простий newLatLngBounds метод в OnCameraChangeListener . Все буде працювати ідеально, і вам не потрібно розраховувати розмір екрану. Ця подія відбувається після розрахунку розміру карти (як я розумію).

Приклад:

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
Це працює, тому що setOnCameraChangeListener гарантовано запускається принаймні один раз після того, як Карта пройшла макет? Це майбутній доказ?
Гленн Бех,

3
@SteelRat Ось чому я був би проти використання рішення. Ви ніколи не знаєте, коли Google змінює це, або навіть якщо це працює так у всіх версіях або пристроях Android.
Glenn Bech

1
@SteelRat Я згоден, але це може бути викликано не раз за весь час діяльності? Я лише наводжу аргумент, що навіть якщо це спрацьовує в цьому випадку, це не дуже елегантне рішення. Я думаю, що OnGlobalLayoutListener / Treelistener - це більш правильний спосіб зробити це.
Гленн Бех

4
можливо, додавання map.moveCamera (CameraUpdateFactory.scrollBy (1, 1)); після того, як наведений вище код зробить фокус?
МОЙ

3
setOnCameraChangeListenerзараз застарів
osrl

56

Ці відповіді просто чудові, але я хотів би підійти до іншого підходу, більш простого. Якщо метод працює лише після того, як карта розкладена, просто почекайте її:

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

1
Після довгих експериментів я виявив, що мені потрібно реалізувати поєднання цієї відповіді та відповіді Даніеле вище. Іноді карта ще не завантажена, інколи макет ще не завершений. Я не міг рухати камеру за бажанням, поки не сталося ОБИХ з них.
RobP

2
Попередження щодо цього методу з документації: "Ця подія не запускатиметься, якщо карта ніколи не завантажується через проблеми з підключенням або якщо карта постійно змінюється і ніколи не завершує завантаження через постійну взаємодію користувача з картою ." (наголос мій).
stkent

1
Це затримується довше, ніж це необхідно, оскільки воно чекає завантаження плиток карти в неправильному положенні, перш ніж перейти у правильне положення.
Джон Паттерсон,

1
Більшу частину часу займає від 3 до 10 секунд, що неприпустимо.
Nima G

Це місце для переміщення камери. Я б запропонував використовувати map.animateCamera, а не map.moveCamera
Бхарат Додея

51

Добре, я це розробив. Як задокументовано тут , API не може використовуватися до верстки.

Правильний API для використання описується так:

Примітка: Використовуйте лише простіший метод newLatLngBounds (межа, відступ) для створення CameraUpdate, якщо він буде використовуватися для переміщення камери після того, як карта пройшла макет. Під час макетування API обчислює межі відображення карти, необхідні для правильного проектування обмежувального вікна. Для порівняння, ви можете використовувати CameraUpdate, повернуту більш складним методом newLatLngBounds (межа, ширина, висота, відступ) у будь-який час, навіть до того, як мапа пройшла макет, оскільки API обчислює межі відображення з переданих вами аргументів.

Щоб вирішити проблему, я розрахував розмір екрану та вказав ширину та висоту

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

Потім це дозволило мені вказати попередній макет обмежувального вікна.


18
Але що, якщо карта займає не весь екран?
theblang

У моєму випадку я просто припустив, що екран більший, ніж був на ділі, і мені потрібно було більш ретельно розрахувати відступ, щоб насправді він був не надто великим. Набагато простіша причина.
rfay

2
Чи можете ви показати, як обчислити його на основі розміру екрану?
Даніель Гомес Ріко

Це не дає збій, але ширина та висота, що використовуються, близькі до чистих здогадок, точна площа, яку потрібно намалювати, насправді непередбачувана.
Вінс,

34

Рішення простіше, ніж це ....

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

Спіймайте IllegalStateExceptionта використовуйте глобальний слухач у поданні. Заздалегідь встановлене розмір прив’язки (попереднє розміщення) за допомогою інших методів означає, що вам потрібно обчислити розмір ПЕРЕГЛЯДУ, а не пристрій екрану. Вони збігаються лише в тому випадку, якщо ви переходите на повноекранний режим із картою і не використовуєте фрагменти.


Дотепер я використовував твій маленький фрагмент, але він все одно не
вдався

1
Як / коли це не вдається? ніколи не мав проблем з цим. Перша відповідь просто передає жорстко закодований розмір як запасний варіант. "Це працює", як у "він більше не аварійно працює", але не робить те саме.
Daniele Segato

@ andrea.spot Я не пам'ятаю, чому я сказав спростити. Припускаю, що прийняте рішення тим часом було відредаговано. Струм загальноприйнятий рішення Припустимо , ваша карта взяти все на екран, що не завжди вірно. Якщо ви не впадете в такому випадку, вам або потрібно знати розмір карти, або скористатися моїм методом або чимось подібним.
Даніеле Сегато

також перевірте відповідь нижче від Xingang Huang, це трохи додає до нього.
Даніеле Сегато,

15

Це моє виправлення, просто почекайте, поки карта не буде завантажена в такому випадку.

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

Простий і ефективний +1
Схід

14

Додавання та видалення маркерів можна виконати до завершення попередньої розкладки, але переміщення камери неможливе (крім використання, newLatLngBounds(boundary, padding)як зазначено у відповіді OP).

Можливо , найкраще місце , щоб виконати початкове оновлення камери використовує один постріл , OnGlobalLayoutListenerяк показано в прикладі коду від Google , наприклад , див наступного уривка з setUpMap()в 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));
        }
    });
}


Я отримую цю помилку при зміні орієнтації. Я також знайшов це за зразком коду, але це не спрацювало для мене. Я все ще отримую ту саму помилку.
osrl

14

Прийнята відповідь не підійде для мене, оскільки мені доводилося використовувати один і той же код у різних місцях мого додатка.

Замість того, щоб чекати зміни камери, я створив просте рішення на основі пропозиції Лі вказати розмір карти. Це на випадок, якщо ваша карта має розмір екрана.

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

Сподіваюся, це допоможе комусь іншому!


8

Прийнята відповідь, як зазначалося в коментарях, трохи хакі. Після його реалізації я помітив надмірно прийнятну кількість IllegalStateExceptionжурналів в аналітиці. Рішення, яке я використав, - це додати файл, OnMapLoadedCallbackв якому CameraUpdateвиконується. Зворотний дзвінок додається до GoogleMap. Після повного завантаження вашої карти оновлення камери буде виконано.

Це призводить до того, що на карті коротко відображається зменшений (0,0) вигляд перед виконанням оновлення камери. Я вважаю, що це є більш прийнятним, ніж спричинення збоїв або покладання на недокументовану поведінку.


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

використовуйте це, це спрацювало для мене


Це просто центрує карту, але не динамічно регулює масштабування до меж.
Джованні Ді Грегоріо

Ми можемо розрахувати межі для більшої кількості маткерів, використовуючи "LatLngBounds.Builder".
Рамеш Бхупаті,

@RameshBhupathi, але він все одно залишатиметься видом на карту з центром та масштабуванням.
Тима

4

У дуже рідкісних випадках макет MapView закінчений, але макет GoogleMap не закінчений, ViewTreeObserver.OnGlobalLayoutListenerсам не може зупинити збій. Я бачив збій з пакетом послуг Google Play версії 5084032. Цей рідкісний випадок може бути спричинений динамічною зміною видимості мого MapView.

Щоб вирішити цю проблему, я вмонтував GoogleMap.OnMapLoadedCallbackв 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));
                    }
                });
            }
        }
    });
}

Цікаво: Якщо я переробляю mapView.getViewTreeObserver()в локальну змінну, виникає така помилка : "IllegalStateException: Цей ViewTreeObserver не активний, знову викликайте getViewTreeObserver ()" . Ви спробували це?
JJD

Якщо mapView.getViewTreeObserver (). IsAlive () випадково виявляється хибним, я б поставив ще один резервний варіант для map.setOnMapLoadedCallback ()
southerton

4

Я використав інший підхід, який працює для останніх версій SDK Карт Google (9.6+) і базується на onCameraIdleListener . Як я бачу, це метод зворотного виклику, який onCameraIdleвикликається завжди після onMapReady. Отже, мій підхід виглядає як цей шматок коду (враховуючи його введення 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
    */
}

4

Я створив спосіб поєднати два зворотних виклики: onMapReady і onGlobalLayout в один єдиний спостережуваний, який буде випромінюватися лише тоді, коли обидві події будуть активовані.

https://gist.github.com/abhaysood/e275b3d0937f297980d14b439a8e0d4a


1
Насправді це найчистіший спосіб вирішити це. Я роблю це вже давно, і жодної помилки в аналітиці не повертається, навіть у додатку 1 тис. Користувачів на день. +1
Скайл

2

Гаразд, я стикаюся з такою ж проблемою. У мене є фрагмент із моїм SupportmapFragment, ABS та шухлядою навігації. Що я зробив:

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...
}

І, до речі, я телефоную resetCamera()з onCreateViewнадуття та перед поверненням.
Що це робить, це вперше вловити виняток (тоді як карта "отримує розмір" як спосіб сказати це ...), а потім, в інший раз, мені потрібно скинути камеру, карта вже має розмір і робить це за допомогою відступів.

Питання пояснюється в документації , там сказано:

Не міняйте камеру за допомогою цього оновлення камери, поки карта не пройде макет (для того, щоб цей метод правильно визначив відповідне обмежувальне поле та рівень масштабування, карта повинна мати розмір). Інакше IllegalStateExceptionбуде кинуто. НЕ достатньо, щоб карта була доступною (тобто getMap()повертає ненульовий об'єкт); вигляд, що містить карту, також повинен мати такий макет, щоб були визначені його розміри. Якщо ви не можете бути впевнені, що це сталося, використовуйте newLatLngBounds(LatLngBounds, int, int, int)замість цього і вручну надайте розміри карти.

Я думаю, що це досить пристойне рішення. Сподіваюся, це комусь допомагає.


1
чи є слухач для прослуховування, коли макет повністю завантажений. ?
Сагар Наяк,

Чи вказано виняток в newLatLngBounds()або в animateCamera(), або в обох? Чи не призведе галузь улову до нового винятку?
CoolMind

1

Якщо вам потрібно почекати, поки почнеться можлива взаємодія з користувачем, використовуйте, OnMapLoadedCallbackяк описано в попередніх відповідях. Але якщо все, що вам потрібно, це вказати місцезнаходження за замовчуванням для карти, немає необхідності в жодному із рішень, викладених у цих відповідях. І те, MapFragmentі MapViewінше може прийняти символ GoogleMapOptionsна початку, який може вказати розташування за замовчуванням. Єдина хитрість полягає не в тому, щоб включити їх безпосередньо у свій макет, оскільки система буде викликати їх без параметрів тоді, а ініціалізувати їх динамічно.

Використовуйте це у своєму макеті:

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

і замініть фрагмент у вашому 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();

Окрім того, що швидше стартувати, перша карта світу не відображатиметься, а камера рухатиметься другою. Карта почнеться із зазначеного місця безпосередньо.


0

Інший підхід мав би щось на зразок (якщо припустити, що ваш найвищий вигляд - це FrameLayout з іменем rootContainer, хоча він буде працювати до тих пір, поки ви завжди вибираєте свій найвищий контейнер, незалежно від того, який тип чи назву він має):

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

Змінення функцій камери працюватиме лише в тому випадку, якщо layoutDoneце trueдозволить вирішити всі ваші проблеми без необхідності додавати додаткові функції або підключати логіку до layoutListenerобробника.


0

Я виявив, що це працює і є простішим за інші рішення:

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

Це повторює виклик знову після запуску макета. Можливо, міг би включити запобіжник, щоб уникнути нескінченного циклу.


0

Чому б просто не використати щось подібне:

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

Чому newLatLngBounds(builder.build(), padding)немає всередині try-catch? Чи трапляється цей виняток у moveCamera()?
CoolMind

0

У репозиторії Google Maps є допоміжний клас, який ви можете використати - він чекає готовності макета та карти, перш ніж повідомляти про зворотний дзвінок за допомогою GoogleMap:

Першоджерело тут:

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

Існує також реалізація Kotlin:

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 (), застаріло , setOnCameraChangeListenerтепер воно застаріло. Отже, вам слід замінити його одним із трьох mtehods:

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

У моєму випадку я використовував OnCameraIdleListenerі всередині видаляв його, оскільки він знову і знову викликався при будь-якому русі.

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

ОНОВЛЕННЯ

Я видалив googleMap.setOnCameraIdleListenerу своєму проекті, оскільки його іноді не викликали, коли показували карту, а зберігали googleMap.setOnCameraIdleListener(clusterManager).


спасибі за вашу відповідь. Я вже знайшов рішення майже таким самим.
Арслан Макбул,

@ArslanMaqbool, дякую! Зараз я в процесі, і буду вдячний вам, якщо ви поділитесь своїм варіантом.
CoolMind

з задоволенням @CoolMind
Arslan

0

У мене була та ж помилка при спробі викликати mMap.animateCamera. Я вирішив це за допомогою виклику setOnMapLoadedCallback зворотного виклику у моїй функції onMapReady, як показано нижче

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

   // other codes go there

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

Це має працювати нормально.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.