animateCamera工作,moveCamera不适用于谷歌地图 - Android



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

我的堆栈跟踪(主要部分):

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.

为什么一种方法知道地图大小而另一种方法不知道?

根据文档,在地图经过布局之前,此 API 无法使用。它说

注意:仅使用更简单的方法newLatLngBounds(边界,填充) 以生成相机更新,如果它要用于移动 地图经过布局后的相机。在布局期间,API 计算地图的显示边界,这是需要的 正确投影边界框。相比之下,您可以使用 相机更新由更复杂的方法返回 newLatLngBounds(边界,宽度,高度,填充)随时,甚至 在地图经过布局之前,因为 API 会计算 显示传递的参数的边界。

但是您可以在OnCameraChangeListener中使用newLatLngBounds()方法。一切都会完美运行,您无需计算屏幕尺寸。据我所知,此事件发生在地图大小计算之后。

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

自从Google Maps SDK更新到最新版本以来,CameraChangeListener被弃用了。我也遇到过这个问题,我发现onCameraIdleListener也有类似的技巧。到目前为止,我所看到的,它是回调方法onCameraIdle总是在onMapReady之后调用。所以我的方法看起来像这段代码(考虑到它放在 Activity 中)用于 Google Maps SDK 9.6+:

@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
    */
}

正如这里清楚地记录的那样 OnMapReadyCallback

请注意,OnMapReadyCallback 不保证地图已经过布局。因此,调用回调方法时可能尚未确定映射的大小。如果您需要知道维度或在 API 中调用需要知道维度的方法,请获取地图的视图并注册 ViewTreeObserver.OnGlobalLayoutListener。

不要链接 OnMapReadyCallback 和 OnGlobalLayoutListener 侦听器,而是独立注册并等待这两个回调,因为回调可以按任何顺序触发。

因此,您必须同时使用(onMapReady,onGlobalLayout)回调来确保map已完全加载并且已确定大小。

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

多亏了@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 毫秒)。

最新更新