animateCamera工作并移动摄影机';t代表谷歌地图-Android

animateCamera工作并移动摄影机';t代表谷歌地图-Android,android,google-maps,illegalstateexception,Android,Google Maps,Illegalstateexception,我需要移动摄像机以覆盖上面的所有标记。因此,我构建LatLngBounds,然后尝试调用mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(LatLngBounds,15))。问题是,当我使用moveCamera()方法时,我得到了IllegalStateException,但当我使用animateCamera()时,它运行得很好。我在onMapReadycallback中调用这两个方法。发生了什么事 我的stacktrace(主要部分): 一

我需要移动摄像机以覆盖上面的所有标记。因此,我构建
LatLngBounds
,然后尝试调用
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(LatLngBounds,15))
。问题是,当我使用
moveCamera()
方法时,我得到了
IllegalStateException
,但当我使用
animateCamera()
时,它运行得很好。我在
onMapReady
callback中调用这两个方法。发生了什么事

我的stacktrace(主要部分):

一种方法知道地图大小而另一种不知道,这怎么可能呢?

根据,在地图经过布局之前,不能使用此API。上面说

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

但是您可以使用
onCamerachenglistener
中的
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更新到最新版本后,它就被弃用了。我也遇到过这个问题,我发现它也有类似的作用。到目前为止,我看到它的回调方法
onCameraIdle
总是在
onMapReady
之后调用。因此,我的方法看起来像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并不保证地图已经过布局。因此,调用回调方法时可能尚未确定映射的大小。如果需要知道维度或调用API中需要知道维度的方法,请获取地图的视图并注册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();
}

多亏了@Viacheslav,我在
SetonCameraideListener
中也做到了这一点:

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

setOnCameraideListener
是移动相机和计算距离的合适侦听器。您也可以在
onMapReady

中获得相同的延迟(100-300毫秒)。您能解释一下为什么animateCamera可以工作而moveCamera不能工作吗?我最后做的就是这个。作品perfectly@Justin如果没有任何代码示例,很难说为什么。从我的角度来看,我可以确认它在最新的MapsAPI上运行良好。您的示例非常有价值,但是如果布局是在地图准备好之前布局的,您如何在
OnGlobalYout()
中执行
initMap()
?如果我错了,很抱歉,但是我相信这应该有一个
if(mMap!=null)
onGlobalLayout
之前检查
initMap()
只是一个预防措施,删除
setOnMapLoadedCallback()
如果使用了它,如果您将它与建议的配置一起使用,它将进入一个循环谢谢您的提示。我尝试了你的代码,添加了
removeOnGlobalLayoutListener
()。在我的例子中,
onGlobalLayout
是在
onMapReady
之前调用的。请参阅@Viacheslav的答案,set
setonCameraideListener
(使用后清除)。
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.
            ...
        }
    }
}