animateCamera工作和移动相机不适用于GoogleMap - Android

时间:2016-01-14 19:25:02

标签: android google-maps illegalstateexception

我需要移动相机以覆盖其上的所有标记。所以,我构建了LatLngBounds,然后尝试调用mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 15))。问题是当我使用moveCamera()方法时,我得到IllegalStateException,但是当我使用animateCamera()时,它就可以了。我在onMapReady回调中调用了这两种方法。发生了什么事?

我的stacktrace(主要部分):

java.lang.IllegalStateException: Error using newLatLngBounds(LatLngBounds, int): Map size can't be 0. Most likely, layout has not yet occured for the map view.  Either wait until layout has occurred or use newLatLngBounds(LatLngBounds, int, int, int) which allows you to specify the map's dimensions.

一个方法怎么可能知道地图大小而另一个方法不知道?

4 个答案:

答案 0 :(得分:1)

根据documentation,在地图进行布局之前,无法使用此API。它说

  

注意:只使用更简单的方法newLatLngBounds(boundary,padding)   如果它将用于移动,则生成一个CameraUpdate   相机在地图上经历了布局。在布局期间,API   计算所需的地图的显示边界   正确投影边界框。相比之下,你可以使用   CameraUpdate由更复杂的方法返回   newLatLngBounds(边界,宽度,高度,填充)随时都可以   在地图经历布局之前,因为API会计算出   显示您传递的参数的边界。

但您可以在newLatLngBounds()中使用OnCameraChangeListener方法。一切都会很完美,你不需要计算屏幕尺寸。据我所知,这个事件发生在地图大小计算之后。

    mMap.setOnCameraChangeListener(new OnCameraChangeListener() {

    @Override
    public void onCameraChange(CameraPosition arg0) {
        // Move camera.
        mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 15));
        // Remove listener to prevent position reset on camera move.
        mMap.setOnCameraChangeListener(null);
    }
});

答案 1 :(得分:0)

由于Google Maps SDK已更新至最新版本onCameraChangeListener,因此已弃用。我也遇到过这个问题,我发现onCameraIdleListener做了类似的伎俩。正如我所看到的那样,它的回调方法onCameraIdle始终在onMapReady之后调用。因此,对于Google Maps SDK 9.6 +,我的方法看起来就像这段代码(考虑到它放在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 :(得分:0)

OnMapReadyCallback

  

请注意,OnMapReadyCallback不保证地图已进行布局。因此,在调用回调方法时,可能尚未确定地图的大小。如果您需要了解尺寸或在API中调用需要了解尺寸的方法,请获取地图的View并注册一个ViewTreeObserver.OnGlobalLayoutListener。

     

请勿链接OnMapReadyCallback和OnGlobalLayoutListener侦听器,而应分别注册并等待两个回调,因为可以按任意顺序触发回调。

因此,您必须同时使用两个(onMapReady,onGlobalLayout)回调,以确保已完全加载地图并确定了大小。

private GoogleMap mMap;
private boolean isMapLoaded;

SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager()
            .findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mapFragment.getView().getViewTreeObserver().addOnGlobalLayoutListener(this);

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    if (!isMapLoaded) {
        isMapLoaded = true;
        return;
    }
    initMap();
}

@Override
public void onGlobalLayout() {
    if (!isMapLoaded) {
        isMapLoaded = true;
        return;
    }
    initMap();
}

private void initMap() {
   //maps fully loaded instance with defined size will be available here.
   //mMap.animateCamera();
   //mMap.moveCamera();
}

答案 3 :(得分:0)

由于@Viacheslav,我在setOnCameraIdleListener中做了同样的事情:

override fun onMapReady(googleMap: GoogleMap?) {
    this.googleMap = googleMap

    // setupMap()

    googleMap?.setOnCameraIdleListener {
        // Remove the listener to stop calling the same event.
        googleMap.setOnCameraIdleListener(null)

        // Now you can use 'moveCamera'.
        // I also added a delay of 100 ms here in order to draw the map 
        // and correctly calculate distances. If this is your case, then add a short pause.
        val position = LatLng(latitude, longitude)
        val camera = CameraUpdateFactory.newLatLngZoom(position, 10)
        // Strange, but it doesn't work for
        // val camera = CameraUpdateFactory.zoomTo(10)
        googleMap.moveCamera(camera)

        // If you later want to listen to camera movements (start-stop),
        // you should change setOnCameraIdleListener here.
        googleMap.setOnCameraIdleListener{
            // A listener for future camera stops.
            ...
        }
    }
}

setOnCameraIdleListener是用于移动相机和计算距离的合适听众。您也可以在onMapReady内以延迟(100-300 ms)获得相同的结果。