Когда вы можете позвонить в GoogleMap.moveCamera после onMapReady из OnMapReadyCallback?

В текущем API Google Maps для Google вы должны позвонить mapFragment.getMapAsync с помощью OnMapReadyCallback, прежде чем вы сможете получить доступ к GoogleMap. Я предположил, что если у вас есть GoogleMap, тогда было бы безопасно вызвать moveCamera(), но я видел отчеты о сбоях с IllegalStateException, который сказал Map size can't be 0. Most likely, layout has not yet occured for the map view.

Итак, я попробовал добавить ViewTreeObserver.OnPreDrawListener и переместить вызов moveCamera() на метод onPreDraw, так как документы для этого говорят "В этот момент все представления в дереве были измерены и заданы рамкой", Но я все еще вижу некоторые отчеты о сбоях с той же проблемой. Я не могу найти документацию для этого - есть вопросы, такие как moveCamera с CameraUpdateFactory.newLatLngBounds сбой, но они предписывают API getMapAsync, поэтому их не так много помощь.

Ответ 1

У меня была такая же проблема. Эта библиотека Google Maps отображает исключение, когда приложение пытается изменить камеру с обновлением этой камеры, пока карта не претерпела макет (чтобы этот метод правильно определял соответствующий ограничивающий прямоугольник и уровень масштабирования, карта должна иметь размер). Здесь описано здесь.

Это мое решение:

@Override
public void onMapReady(GoogleMap googleMap) {
    googleMap.setOnMapLoadedCallback(this);
}

@Override
public void onMapLoaded() {
    googleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(…));
}

Ответ 2

У меня была та же проблема. Я адаптировал решение из предоставленной вами ссылки, которая, похоже, работает на меня. В onCreate():

rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    public void onGlobalLayout() {displayMap();}
});

OnGlobalLayoutListener(), по-видимому, вызывается несколько раз для каждого макета, поэтому, возможно, более точно назначенный слушатель будет лучше. Чтобы избежать неэффективности манипулирования картой больше, чем необходимо, я использовал булевский mMapInitialised.

onMapReady():

@Override public void onMapReady(GoogleMap map) {
    mMap =  map;
    displayMap();   // if width of MapFragment is known
}

displayMap():

void displayMap() {
    // Check that mMap has been initialised AND the width of the MapFragment has been set:
    if (mMapInitialised || mMap==null) return;
    if (mMapFragment.getView().getRight() <= 0) return;
    LatLngBounds bounds = new LatLngBounds(new LatLng(mLat_min,mLng_min), new LatLng(mLat_max,mLng_max));
    CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(bounds, 10);
    mMap.moveCamera(cameraUpdate);
    mMapInitialised = true;
}

Ответ 3

Вы можете делать все, что захотите, сразу после вызова onMapReady (GoogleMap googleMap).

Это работает прямо сейчас в mi app:

mapFragment.getMapAsync(new OnMapReadyCallback() {

            @Override
            public void onMapReady(GoogleMap googleMap) {

                map = googleMap;
                map.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(usr.getLatitud(), usr.getLongitud()), 14.6f));
            }
});