自 2016 年 8 月以来的更新
总结现在这个问题的正确答案是使用新onCameraIdle
的,而不是OnCameraChangeListener
现在已弃用的。阅读下面的方法。
现在,您可以在最新版本的 Android 版 Google 地图上收听“dragEnd”类事件,甚至其他事件。
如文档中所示,您可以通过使用新的侦听器来避免多次(又名“多次”)调用的问题。OnCameraChangeListener
例如,您现在可以检查相机移动的原因是什么,这是fetchData
根据要求解决问题的理想选择。以下代码大多直接取自文档。还有一件事,有必要使用Google Play Services 9.4。
public class MyCameraActivity extends FragmentActivity implements
OnCameraMoveStartedListener,
OnCameraMoveListener,
OnCameraMoveCanceledListener,
OnCameraIdleListener,
OnMapReadyCallback {
private GoogleMap mMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_camera);
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap map) {
mMap = map;
mMap.setOnCameraIdleListener(this);
mMap.setOnCameraMoveStartedListener(this);
mMap.setOnCameraMoveListener(this);
mMap.setOnCameraMoveCanceledListener(this);
// Show Sydney on the map.
mMap.moveCamera(CameraUpdateFactory
.newLatLngZoom(new LatLng(-33.87365, 151.20689), 10));
}
@Override
public void onCameraMoveStarted(int reason) {
if (reason == OnCameraMoveStartedListener.REASON_GESTURE) {
Toast.makeText(this, "The user gestured on the map.",
Toast.LENGTH_SHORT).show();
} else if (reason == OnCameraMoveStartedListener
.REASON_API_ANIMATION) {
Toast.makeText(this, "The user tapped something on the map.",
Toast.LENGTH_SHORT).show();
} else if (reason == OnCameraMoveStartedListener
.REASON_DEVELOPER_ANIMATION) {
Toast.makeText(this, "The app moved the camera.",
Toast.LENGTH_SHORT).show();
}
}
@Override
public void onCameraMove() {
Toast.makeText(this, "The camera is moving.",
Toast.LENGTH_SHORT).show();
}
@Override
public void onCameraMoveCanceled() {
Toast.makeText(this, "Camera movement canceled.",
Toast.LENGTH_SHORT).show();
}
@Override
public void onCameraIdle() {
Toast.makeText(this, "The camera has stopped moving. Fetch the data from the server!", Toast.LENGTH_SHORT).show();
LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;
fetchData(bounds)
}
}
2016 年 8 月之前有效解决方案的解决方法
由于这个问题得到了正确的回答,我想补充一下可能是下一个问题的问题。
OnCameraChangeListener
由于触发此方法的频率,使用从服务器获取数据时会出现问题。
有一个问题报告了在进行简单的地图滑动时触发此方法的频率有多疯狂,因此在问题的示例中fetchData
,即使没有相机更改,它也会触发多个连续时间以进行非常小的相机更改,是的,它发生了相机边界没有改变,但该方法被触发。
这可能会影响服务器端的性能,并且会通过从服务器按顺序获取数据数十次而浪费大量设备资源。
您可以在该链接中找到此问题的解决方法,但还没有正式的方法来解决此问题,例如,使用期望dragEnd
的 或cameraChangeEnd
回调。
下面的一个例子,基于那里的例子,是我如何通过使用调用的时间间隔并丢弃具有相同边界的调用来避免上述问题。
// Keep the current camera bounds
private LatLngBounds currentCameraBounds;
new GoogleMap.OnCameraChangeListener() {
private static int CAMERA_MOVE_REACT_THRESHOLD_MS = 500;
private long lastCallMs = Long.MIN_VALUE;
@Override
public void onCameraChange(CameraPosition cameraPosition) {
LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
// Check whether the camera changes report the same boundaries (?!), yes, it happens
if (currentCameraBounds.northeast.latitude == bounds.northeast.latitude
&& currentCameraBounds.northeast.longitude == bounds.northeast.longitude
&& currentCameraBounds.southwest.latitude == bounds.southwest.latitude
&& currentCameraBounds.southwest.longitude == bounds.southwest.longitude) {
return;
}
final long snap = System.currentTimeMillis();
if (lastCallMs + CAMERA_MOVE_REACT_THRESHOLD_MS > snap) {
lastCallMs = snap;
return;
}
fetchData(bounds);
lastCallMs = snap;
currentCameraBounds = bounds;
}