En sachant quand la carte a cessé de faire défiler (comme "moveend" dans javascript API)

Je dois détecter quand un MapView a été défilé ou zoomé, comme l'événement "moveend" dans l'API javascript. J'aimerais attendre jusqu'à ce que la vue ait cessé de bouger, de sorte que je peux détecter si j'ai besoin d'interroger mon serveur pour des éléments contenant le rectangle de visualisation et, si tel est le cas, envoyer une demande. (En fait, j'envoie une demande pour une zone légèrement plus grande que le rectangle de visualisation)

Évidemment, je préfère ne pas envoyer de demande de données si la vue est encore en mouvement. Mais pire encore, c'est que je ne sais pas si j'ai besoin d'envoyer une autre demande, en laissant des zones de la carte des marqueurs manquants.

  • Recycler voir l'article compléter la taille complète de la vue du recycleur après la mise à niveau de la bibliothèque de support de "23.1.1" à "23.2.1"
  • Comment dessiner une roue sur toile?
  • Java.lang.RuntimeException: WakeLock sous verrouillé C2DM_LIB
  • Comment arrêter Handler Runnable?
  • Constantement sur la reconnaissance de la parole en écoutant un seul mot-clé
  • Largeur en pourcentage dans un rapportLayout
  • Actuellement, je sous-classe MapView et manipule onTouchEvent comme suit:

    public boolean onTouchEvent(android.view.MotionEvent ev) { super.onTouchEvent (ev); if (ev.getAction() == MotionEvent.ACTION_UP) { GeoPoint center = getMapCenter(); int latSpan = getLatitudeSpan(), lngSpan = getLongitudeSpan(); /* (check if it has moved enough to need a new set of data) */ } return true; } 

    Le problème est que je ne sais pas si la vue s'est arrêtée, car le défilement tend à avoir de l'inertie et peut continuer à passer l'événement "ACTION_UP".

    Y at-il un événement sur lequel je peux exploiter qui m'indiquera quand une vue de carte est terminée en mouvement (ou en zoom)? Sinon, est-ce que quelqu'un a écrit une logique pour détecter cela? En théorie, je pouvais faire une estimation en regardant toutes les actions, et mettre quelque chose à venir un peu plus tard et le vérifier … mais … cela semble désordonné et un PITA. Mais si quelqu'un l'a déjà écrit … 🙂

    5 Solutions collect form web for “En sachant quand la carte a cessé de faire défiler (comme "moveend" dans javascript API)”

    Je n'ai pas vraiment une solution satisfaisante à ce problème, mais je peux dire ce que j'ai fait pour le résoudre partiellement.

    • J'ai computeScroll() et computeScroll() méthode computeScroll() , qui obtient le point central actuel de la carte et le compare avec le point central le plus connu (stocké comme un champ volatile dans la sous-classe). Si le point central a changé, il déclenche un événement sur l'auditeur de la carte (j'ai défini une interface d'écoute personnalisée pour cela).
    • L'auditeur est une activité qui instancie une sous-classe d' AsyncTask et l'exécute. Cette tâche fait une pause de doInBackGround() dans sa méthode doInBackGround() , avant d'effectuer l'extraction des données du serveur.
    • Lorsque l'activité de l'auditeur reçoit un deuxième événement de déplacement de la carte (ce qu'il fera en raison de l'effet de progression du mouvement de la carte), il vérifie l'état du AsyncTask exécuté AsyncTask . Si cette tâche est toujours en cours, elle cancel() elle. Il crée alors une nouvelle tâche, et l'exécute.

    L'effet global est que lorsque les auditeurs obtiennent la vitesse des événements déplacés par la carte à quelques millisecondes, le seul qui déclenche la tâche pour effectuer l'extraction du serveur est le dernier de la séquence. L'inconvénient est qu'il introduit un léger retard entre le mouvement de la carte qui se passe et que l'extraction du serveur se produit.

    Je ne suis pas contente, c'est moche, mais cela atténue le problème. J'aimerais voir une meilleure solution à cela.

    C'est la méthode que j'utilise actuellement, j'ai utilisé cela et l'ai testé, fonctionne bien. Assurez-vous simplement de rendre votre méthode draw() efficace. (Évitez GC en elle).

     //In map activity class MyMapActivity extends MapActivity { protected void onCreate(Bundle savedState){ setContent(R.layout.activity_map); super.onCreate(savedSate); OnMapMoveListener mapListener = new OnMapMoveListener(){ public void mapMovingFinishedEvent(){ Log.d("MapActivity", "Hey look! I stopped scrolling!"); } } // Create overlay OnMoveOverlay mOnMoveOverlay = new OnMoveOverlay(mapListener); // Add overlay to view. MapView mapView = (MapView)findViewById(R.id.map_view); // Make sure you add as the last overlay so its on the top. // Otherwise other overlays could steal the touchEvent; mapView.getOverlays().add(mOnMoveOverlay); } } 

    C'est votre classe OnMoveOverlay

     //OnMoveOverlay class OnMoveOverlay extends Overlay { private static GeoPoint lastLatLon = new GeoPoint(0, 0); private static GeoPoint currLatLon; // Event listener to listen for map finished moving events private OnMapMoveListener eventListener = null; protected boolean isMapMoving = false; public OnMoveOverlay(OnMapMoveListener eventLis){ //Set event listener eventListener = eventLis; } @Override public boolean onTouchEvent(android.view.MotionEvent ev) { super.onTouchEvent(ev); if (ev.getAction() == MotionEvent.ACTION_UP) { // Added to example to make more complete isMapMoving = true; } //Fix: changed to false as it would handle the touch event and not pass back. return false; } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { if (!shadow) { if (isMapMoving) { currLatLon = mapView.getProjection().fromPixels(0, 0); if (currLatLon.equals(lastLatLon)) { isMapMoving = false; eventListener.mapMovingFinishedEvent(); } else { lastLatLon = currLatLon; } } } } public interface OnMapMoveListener{ public void mapMovingFinishedEvent(); } } 

    eventListener.mapMovingFinishedEvent(); simplement votre propre auditeur eventListener.mapMovingFinishedEvent(); Et tirez la carte en mouvement bool par une autre méthode comme ci-dessus et votre tri.

    L'idée est que lorsque la carte déplace la projection des pixels vers les coordonnées, elles changeront, une fois qu'elles sont identiques, vous avez fini de vous déplacer.

    J'ai mis à jour ce code plus récent et plus complet, il y avait un problème avec le double dessin.

    Nous ne faisons rien sur le passage de l'ombre car nous calculons simplement le calcul par tirage au sort qui est un gaspillage.

    N'hésitez pas à poser des questions 🙂

    Merci Chris

    J'ai eu le même problème et l'ai "résolu" d'une manière similaire, mais je pense que c'est moins compliqué: comme le computeScroll () n'a pas fonctionné pour moi, j'ai trop sur TooEvent. Ensuite, j'ai utilisé un Handler, qui invoque un appel de méthode après 50 ms, si le centre de carte a changé, il en va de même si le centre de carte n'a pas changé, l'auditeur s'appelle. La méthode que j'appelle dans onTouchEvent ressemble à ceci:

     private void refreshMapPosition() { GeoPoint currentMapCenter = getMapCenter(); if (oldMapCenter==null || !oldMapCenter.equals(currentMapCenter)) { oldMapCenter = currentMapCenter; handler.postDelayed(new Runnable() { @Override public void run() { refreshMapPosition(); } }, 50); } else { if (onScrollEndListener!=null) onScrollEndListener.onScrollEnd(currentMapCenter); } } 

    Mais j'attends une vraie solution pour cela, aussi …

    Je l'ai résolu à l'aide d'un fil et cela semble fonctionner très bien. Il détecte non seulement les changements de centre, mais aussi les changements de zoom. Eh bien, la détection se fait après la fin du zoom et du défilement. Si vous devez détecter les changements de zoom lorsque vous déplacez le premier doigt, vous pouvez modifier mon code un peu pour détecter différents pointeurs. Mais je n'en ai pas besoin, alors je ne l'ai pas inclus et j'ai laissé des devoirs pour vous: D

     public class CustomMapView extends MapView { private GeoPoint pressGP; private GeoPoint lastGP; private int pressZoom; private int lastZoom; public boolean onTouchEvent( MotionEvent event ) { switch( event.getAction() ) { case MotionEvent.ACTION_DOWN: pressGP = getMapCenter(); pressZoom = getZoomLevel(); break; case MotionEvent.ACTION_UP: lastGP = getMapCenter(); pressZoom = getZoomLevel(); if( !pressGP.equals( lastGP ) ) { Thread thread = new Thread() { public void run() { while( true ) { try { Thread.sleep( 100 ); } catch (InterruptedException e) {} GeoPoint gp = getMapCenter(); int zl = getZoomLevel(); if( gp.equals( lastGP ) && zl == lastZoom) break; lastGP = gp; lastZoom = zl; } onMapStop( lastGP ); } }; thread.start(); } break; } return super.onTouchEvent( event ); } public void onMapStop( GeoPoint point , int zoom ){ // PUT YOUR CODE HERE } } 

    Avec la dernière version de google maps API (V2), il y a un auditeur pour le faire, c'est-à-dire GoogleMap.OnCameraChangeListener .

     mGoogleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() { @Override public void onCameraChange(CameraPosition cameraPosition) { Toast.makeText(mActivity, "Longitude : "+cameraPosition.target.longitude +", Latitude : "+cameraPosition.target.latitude, Toast.LENGTH_SHORT).show(); } }); 
    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.