Existe-t-il un moyen simple d'obtenir le LatLngBounds
de la carte visible à partir d'un CameraPosition
avec Android API Google Maps v2 afin que je puisse utiliser le OnCameraChangeListener
pour aller chercher de nouvelles données pour les marqueurs.
mMap.setOnCameraChangeListener(new OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition position) {
LatLngBounds bounds = ?;
fetchNewData(bounds);
}
});
Mise à jour depuis août 2016
Résumé la réponse correcte maintenant pour ce problème est d'utiliser le nouveau onCameraIdle
, au lieu de OnCameraChangeListener
, qui est maintenant obsolète . Lisez ci-dessous comment.
Vous pouvez désormais écouter des événements de type "dragEnd" et même d'autres événements sur la dernière version de Google Maps pour Android.
Comme indiqué dans les docs , vous pouvez éviter le problème des appels multiples (aka " plusieurs") des OnCameraChangeListener
en utilisant les nouveaux écouteurs. Par exemple, vous pouvez maintenant vérifier quelle est la raison du déplacement de la caméra, ce qui est idéal pour coupler avec un problème fetchData
comme demandé. Le code suivant est principalement directement extrait de la documentation. Encore une chose, il est nécessaire d'utiliser 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)
}
}
Solution de contournement pour une solution efficace avant août 2016
Comme la question est correctement répondue, je voudrais ajouter à cela sur un prochain problème.
Le problème survient lors de l'utilisation de OnCameraChangeListener
pour extraire des données du serveur en raison de la fréquence à laquelle cette méthode est déclenchée.
Il y a un problème signalé sur la fréquence à laquelle cette méthode est déclenchée de manière folle lors d'un glissement de carte simple, donc dans l'exemple de la question, elle déclencherait fetchData
plusieurs temps séquentiels pour très peu la caméra change, même pour aucune caméra, oui, il arrive que les limites de la caméra n'aient pas changé, mais la méthode est déclenchée.
Cela pourrait avoir un impact sur les performances côté serveur et gaspillerait beaucoup de ressources des appareils en récupérant les données séquentiellement des dizaines de fois depuis le serveur.
Vous pouvez trouver dans ce lien des solutions de contournement pour ce problème, mais il n'y a pas encore de moyen officiel de le faire, par exemple, en utilisant les rappels souhaitables dragEnd
ou cameraChangeEnd
.
Un exemple ci-dessous, basé sur ceux de là, est la façon dont j'évite le problème susmentionné en jouant avec l'intervalle de temps des appels et en rejetant les appels avec les mêmes limites.
// 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;
}
Vous ne pouvez pas obtenir les LatLngBounds de la CameraPosition, mais vous pouvez les obtenir facilement à partir de GoogleMap.
private GoogleMap mMap;
mMap.setOnCameraChangeListener(new OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition position) {
LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;
fetchData(bounds);
}
});