CameraUpdateFactory.newLatLngBounds가있는 moveCamera가 다운 됨


96

새로운 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 개체에 그리는 가장 좋은 장소 입니까, 아니면 마커를 그리고 다른 곳에 카메라 위치를 설정해야합니까?

답변:


133

OnCameraChangeListener 에서 간단한 newLatLngBounds 메소드를 사용할 수 있습니다 . 모두 완벽하게 작동하며 화면 크기를 계산할 필요가 없습니다. 이 이벤트는지도 크기 계산 후에 발생합니다 (내가 이해 한대로).

예:

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
이것은 Map이 레이아웃을 거친 후 setOnCameraChangeListener가 적어도 한 번 실행되도록 보장되기 때문에 작동합니까? 이것이 미래의 증거입니까?
Glenn Bech

3
@SteelRat 그게 내가 솔루션 사용에 반대하는 이유입니다. Google이 언제 이것을 변경하는지, 또는 모든 Android 버전 또는 장치에서 그렇게 작동하는지 알 수 없습니다.
Glenn Bech

1
@SteelRat 동의하지만 활동 기간 동안 두 번 이상 호출 될 수 있습니까? 이 경우에 작동하더라도 매우 우아한 해결책이 아니라는 주장을하고 있습니다. 나는 OnGlobalLayoutListener / Treelistener가 이것에 대해 더 올바른 방법이라고 생각합니다.
Glenn Bech

4
아마도 map.moveCamera (CameraUpdateFactory.scrollBy (1, 1)); 위의 코드가 트릭을 만들까요?
MY

3
setOnCameraChangeListener지금은 사용되지 않습니다
osrl

56

그 대답은 괜찮지 만 다른 접근 방식, 더 간단한 접근 방식을 선택하겠습니다. 지도가 배치 된 후에 만 ​​메서드가 작동하는 경우 기다리십시오.

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

1
많은 실험 끝에이 답변과 위의 Daniele의 조합 을 구현해야한다는 것을 알았습니다 . 지도가 아직로드되지 않은 경우도 있고 레이아웃이 아직 완료되지 않은 경우도 있습니다. 두 가지가 모두 일어날 때까지 카메라를 원하는대로 이동할 수 없었습니다.
RobP 2014-06-14

2
문서에서이 방법에 대한 경고 : "연결 문제로 인해지도가로드되지 않거나지도가 지속적으로 변경되고 사용자가지도와 지속적으로 상호 작용하여로드를 완료 하지 않는 경우이 이벤트가 발생하지 않습니다 ." (강조 내).
stkent

1
올바른 위치로 이동하기 전에지도 타일이 잘못된 위치에서로드 될 때까지 기다리기 때문에 필요한 것보다 오래 지연됩니다.
John Patterson

1
대부분의 경우 용납 할 수없는 발사에 3-10 초가 걸립니다.
Nima G

카메라를 이동하는 곳입니다. map.moveCamera 대신 map.animateCamera를 사용하는 것이 좋습니다
Bharat Dodeja

51

알았어. 로 여기에 문서화 하는 API는 사용되는 사전 배치 할 수 없습니다.

사용할 올바른 API는 다음과 같이 설명됩니다.

참고 :지도가 레이아웃을 완료 한 후 카메라를 이동하는 데 사용되는 경우 더 간단한 메소드 newLatLngBounds (boundary, padding) 만 사용하여 CameraUpdate를 생성하세요. 레이아웃 중에 API는 경계 상자를 올바르게 투영하는 데 필요한지도의 표시 경계를 계산합니다. 이에 비해 API는 전달하는 인수에서 표시 경계를 계산하므로지도가 레이아웃을 수행하기 전이라도 더 복잡한 메소드 newLatLngBounds (boundary, width, height, padding)에서 반환 한 CameraUpdate를 언제든지 사용할 수 있습니다.

문제를 해결하기 위해 화면 크기를 계산하고 너비와 높이를

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

그러면 경계 상자 사전 레이아웃을 지정할 수 있습니다.


18
하지만지도가 전체 화면을 차지하지 않으면 어떻게 될까요?
theblang

제 경우에는 그냥 효과보다 더 큰 화면을 가정, 그것은 사실이었다, 그래서 더 조심스럽게 패딩을 계산하기 위해 필요했던 하지 너무 큽니다. 훨씬 더 간단한 이유입니다.
rfay

2
화면 크기를 기준으로 계산하는 방법을 보여줄 수 있습니까?
Daniel Gomez Rico

이것은 충돌하지 않지만 사용할 너비와 높이는 순수한 추측에 가깝습니다. 그릴 정확한 영역은 실제로 예측할 수 없습니다.
Vince

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대신 뷰에서 글로벌 리스너를 잡아서 사용하십시오. 다른 방법을 사용하여 미리 경계 크기를 설정 (사전 레이아웃)하면 화면 장치가 아닌 THE VIEW의 크기를 계산해야합니다. 지도로 전체 화면으로 이동하고 조각을 사용하지 않는 경우에만 일치합니다.


지금까지 작은 스 니펫을 사용해 왔지만 여전히 실패합니다 ... 정답은 첫 번째입니다 :-)
cesards

1
어떻게 / 언제 실패합니까? 이것에 문제가 없었습니다. 첫 번째 답변은 하드 코딩 된 크기를 대체로 전달합니다. "더 이상 충돌하지 않습니다"와 같이 "작동"하지만 동일한 작업을 수행하지 않습니다.
Daniele Segato 2013 년

@ andrea.spot 내가 왜 더 간단하게 말했는지 기억이 나지 않습니다. 그동안 수락 된 솔루션이 편집 된 것 같습니다. 현재 허용 솔루션은 맵이 항상 사실이 아니다 모든 화면을 가지고 가정합니다. 이 경우에 빠지지 않으면지도의 크기를 알거나 내 방법 또는 유사한 방법을 사용해야합니다.
Daniele Segato

또한 Xingang Huang의 아래 답변을 확인하면 약간 추가됩니다.
Daniele Segato 2015-07-17

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
Shid

14

마커 추가 및 제거는 사전 레이아웃 완료로 수행 할 수 있지만 카메라를 이동할 수는 없습니다 ( newLatLngBounds(boundary, padding)OP의 답변에 명시된대로 사용 하는 경우 제외 ).

아마 초기 카메라 업데이트를 수행하는 가장 좋은 장소는 원샷을 사용하고 OnGlobalLayoutListener같이 구글의 샘플 코드 예로부터 발췌 한 다음 코드를 참조 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

내 앱의 여러 위치에서 동일한 코드를 사용해야했기 때문에 받아 들여진 대답이 작동하지 않았습니다.

카메라가 바뀔 때까지 기다리는 대신지도 크기를 지정하라는 Lee의 제안에 따라 간단한 솔루션을 만들었습니다. 지도가 화면 크기 인 경우입니다.

// 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분석에서 허용 가능한 양 이상의 로그를 발견했습니다 . 내가 사용한 해결책 OnMapLoadedCallbackCameraUpdate이 수행 되는 을 추가하는 것 입니다 . 콜백이 GoogleMap. 지도가 완전히로드되면 카메라 업데이트가 수행됩니다.

이렇게하면 카메라 업데이트를 수행하기 전에지도에 축소 된 (0,0) 뷰가 잠깐 표시됩니다. 나는 이것이 충돌을 일으키거나 문서화되지 않은 행동에 의존하는 것보다 더 수용 가능하다고 생각합니다.


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

나를 위해 일한 이것을 사용하십시오


이것은 단지지도의 중앙에 위치하지만 확대 / 축소를 경계로 동적으로 조정하지는 않습니다.
Giovanni Di Gregorio

"LatLngBounds.Builder"를 사용하여 더 많은 matker에 대한 경계를 계산할 수 있습니다.
Ramesh Bhupathi 2015

@RameshBhupathi하지만 여전히 중앙과 확대 / 축소가있는지도보기로 유지됩니다.
Tima

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

최신 버전의 Google Maps SDK (9.6+)에서 작동하고 onCameraIdleListener를 기반으로하는 다른 접근 방식을 사용 했습니다 . 지금까지 보았 듯이 onCameraIdlealways after라는 콜백 메서드 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
    */
}


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(), null이 아닌 객체를 반환합니다). 지도가 포함 된 뷰도 크기가 결정되는 레이아웃을 거쳐야합니다. 이것이 발생했는지 확신 할 수없는 경우 newLatLngBounds(LatLngBounds, int, int, int)대신 사용 하고지도의 치수를 수동으로 제공하십시오.

꽤 괜찮은 해결책이라고 생각합니다. 누군가에게 도움이되기를 바랍니다.


1
레이아웃이 완전히로드되었을 때 수신 할 리스너가 있습니까? ?
Sagar Nayak

에서 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

또 다른 접근 방식은 다음과 같습니다 ( rootContainer어떤 유형이나 이름에 관계없이 항상 최상위 컨테이너를 선택하는 한 작동하지만 최상위 뷰가라는 FrameLayout이라고 가정 ).

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

경우에만 작업에 카메라 기능을 수정 layoutDoneIS가 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지도 저장소에는 활용할 수있는 도우미 클래스가 있습니다. GoogleMap으로 콜백을 알리기 전에 레이아웃과지도가 모두 준비 될 때까지 기다립니다.

원본 출처는 다음과 같습니다.

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

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지금은 사용되지 않습니다. 따라서 다음 세 가지 방법 중 하나로 대체해야합니다.

  • 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).


답장을 보내 주셔서 감사합니다. 이미 이와 거의 같은 해결책을 찾고 있습니다.
Arslan Maqbool

@ArslanMaqbool, 감사합니다! 현재 진행 중이며 변형을 공유해 주시면 감사하겠습니다.
CoolMind

@CoolMind 내 기쁨
Arslan Maqbool

0

mMap.animateCamera를 호출하는 데 동일한 오류가 발생했습니다. 아래에 표시된대로 내 onMapReady 함수 에서 setOnMapLoadedCallback 콜백 을 호출하여 문제를 해결했습니다.

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

   // other codes go there

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

이것은 잘 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.