web-dev-qa-db-fra.com

API Google Maps v2: LatLngBounds de CameraPosition

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

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;

}
35
Eduardo

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