2010-02-24 20 views

Respuesta

0

La única forma en que se me ocurre es ampliar el MapView y anular el OnTouchEvent y observar la acción Up. Esto le dirá que el usuario ha terminado de moverse y puede obtener el lapso de latitud/longitud para determinar la región que debe verificar.

+0

esto no funciona si el usuario arroja el mapa ya que el mapa se asentará después de la acción UP – Dori

4

intento MapView-overlay-manager, que es una extensión para sobrecapa de mapas para Android,

tiene algo simplificada OnGestureListener, pocos ejemplo:

onSingleTap(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem) 

onDoubleTap(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem) 

onLongPress(MotionEvent, ManagedOverlay, GeoPoint, OverlayItem) 

onZoom(ZoomEvent, ManagedOverlay) 

onScrolled(...) 

enlace: http://code.google.com/p/mapview-overlay-manager/ creo que sirve

1

Lamentablemente, no existe una función integrada para hacer esto en las herramientas de MapView (un extraño descuido ya que esta funcionalidad está en el SDK de JavaScript, así como en el SDK de iOS).

Sin embargo, puede hacer frente a esto con la facilidad de usar un Runnable y simplemente sondear el MapView. Lo hago por no perder de vista el estado "último" de:

getLatitudeSpan(); 
getLongitudeSpan(); 
getCenter(); 
getZoomLevel(); 

y luego los compara con los valores actuales. Si cambian los valores, sabrá que la vista del mapa se ha movido. Si no, no puedes hacer nada.

De cualquier forma, reprograme el ejecutable para otra ejecución después de 500ms o más y repita el proceso. Puede usar onResume() y onPause() para eliminar la devolución de llamada de Runnable y reiniciarlo según sea necesario.

+1

"Lamentablemente, no hay funcionalidad incorporada para hacer esto en las herramientas MapView" no, el método onLayout maneja esto con bastante gracia, vea mi respuesta para un ejemplo. –

1

La clase MapView puede seguir los cambios utilizando el método onLayout.

decir

class CustomMapView extends MapView { 

    protected void onLayout(boolean changed,int left, int right, int top, int bottom){ 
     super.onLayout(changed,left, right, top, bottom); 
     if(changed){ 
     // do something special 
     } 
    } 
} 
+2

Pruebas en Gingerbread para tres interacciones de mapa (PAN con el dedo, ZOOM a través de controles, PINCH/REVERSE PINCH con dos dedos), esto es lo que obtuve: 1) PAN: hay múltiples eventos onLayout con changed = true 2) ZOOM: allí es un evento con changed = true, múltiples eventos con changed = false 3) PINCH/REVERSE PINCH: no hay eventos con changed = true, múltiples eventos con changed = false. Por lo tanto, con este método puede detectar PAN simple con los dedos/ZOOM a través de cambios de controles, pero no puede detectar los cambios realizados con PINCH/REVERSE PINCH. – Theo

3

Se puede crear un SimpleMapView que se extiende MapView.

public class SimpleMapView extends MapView { 

    private int currentZoomLevel = -1; 
    private GeoPoint currentCenter; 
    private List<ZoomChangeListener> zoomEvents = new ArrayList<ZoomChangeListener>(); 
    private List<PanChangeListener> panEvents = new ArrayList<PanChangeListener>(); 

    public SimpleMapView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    public SimpleMapView(Context context, String apiKey) { 
     super(context, apiKey); 
    } 

    public SimpleMapView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 
    /** 
    * 
    * @return 
    */ 
    public int[][] getBounds() { 

     GeoPoint center = getMapCenter(); 
     int latitudeSpan = getLatitudeSpan(); 
     int longtitudeSpan = getLongitudeSpan(); 
     int[][] bounds = new int[2][2]; 

     bounds[0][0] = center.getLatitudeE6() - (latitudeSpan/2); 
     bounds[0][1] = center.getLongitudeE6() - (longtitudeSpan/2); 

     bounds[1][0] = center.getLatitudeE6() + (latitudeSpan/2); 
     bounds[1][1] = center.getLongitudeE6() + (longtitudeSpan/2); 
     return bounds; 
    } 

    public boolean onTouchEvent(MotionEvent ev) { 
     if (ev.getAction() == MotionEvent.ACTION_UP) { 
      GeoPoint centerGeoPoint = this.getMapCenter(); 
      if (currentCenter == null || 
        (currentCenter.getLatitudeE6() != centerGeoPoint.getLatitudeE6()) || 
        (currentCenter.getLongitudeE6() != centerGeoPoint.getLongitudeE6())) { 
       firePanEvent(currentCenter, this.getMapCenter()); 
      } 
      currentCenter = this.getMapCenter(); 
     } 
     return super.onTouchEvent(ev); 
    } 

    @Override 
    protected void dispatchDraw(Canvas canvas) { 
     super.dispatchDraw(canvas); 
     if(getZoomLevel() != currentZoomLevel){ 
      fireZoomLevel(currentZoomLevel, getZoomLevel()); 
      currentZoomLevel = getZoomLevel(); 
     } 
    } 

    @Override 
    public void setSatellite(boolean on){ 
     super.setSatellite(on); 
    } 

    @Override 
    public MapController getController(){ 
     return super.getController(); 
    } 

    private void fireZoomLevel(int old, int current){ 
     for(ZoomChangeListener event : zoomEvents){ 
      event.onZoom(old, current); 
     } 
    } 

    private void firePanEvent(GeoPoint old, GeoPoint current){ 
     for(PanChangeListener event : panEvents){ 
      event.onPan(old, current); 
     } 
    } 

    public void addZoomChangeListener(ZoomChangeListener listener){ 
     this.zoomEvents.add(listener); 
    } 

    public void addPanChangeListener(PanChangeListener listener){ 
     this.panEvents.add(listener); 
    } 
} 

Tiene los Oyentes puede poner el código para pan o zoom. Luego, en el xml:

<com.androidnatic.maps.SimpleMapView android:clickable="true" 
        android:layout_height="match_parent" android:id="@+id/mapView" 
        android:layout_width="match_parent" 
        android:apiKey="xxx"> 
</com.androidnatic.maps.SimpleMapView> 

Y luego, en su código puede especificar el Pan Oyente:

mapView.addPanChangeListener(new PanChangeListener() { 

      @Override 
      public void onPan(GeoPoint old, GeoPoint current) { 
          //TODO 
         } 
     }); 
0

vieja pregunta, pero me escribió una clase hace un tiempo llamado ExMapView que dispara un evento cuando la región del mapa comienza a cambiar (onRegionBeginChange) y cuando deja de cambiar (onRegionEndChange). Esta clase es para usar con el viejo MapView, no con V2.0. Espero que ayude a alguien.

import android.content.Context; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 

import com.google.android.maps.GeoPoint; 
import com.google.android.maps.MapView; 

public class ExMapView extends MapView { 
    private static final String TAG = ExMapView.class.getSimpleName(); 
    private static final int DURATION_DEFAULT = 700; 

    private OnRegionChangedListener onRegionChangedListener; 
    private GeoPoint previousMapCenter; 
    private int previousZoomLevel; 
    private int changeDuration; // This is the duration between when the user stops moving the map around and when the onRegionEndChange event fires. 
    private boolean isTouched = false; 
    private boolean regionChanging = false; 

    private Runnable onRegionEndChangeTask = new Runnable() { 
     public void run() { 
      regionChanging = false; 
      previousMapCenter = getMapCenter(); 
      previousZoomLevel = getZoomLevel(); 
      if (onRegionChangedListener != null) { 
       onRegionChangedListener.onRegionEndChange(ExMapView.this, previousMapCenter, previousZoomLevel); 
      } 
     } 
    }; 

    public ExMapView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public ExMapView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(); 
    } 

    public ExMapView(Context context, String apiKey) { 
     super(context, apiKey); 
     init(); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     isTouched = event.getAction() != MotionEvent.ACTION_UP; 
     return super.onTouchEvent(event); 
    } 

    @Override 
    public void computeScroll() { 
     super.computeScroll(); 

     // If the map region is still changing (user is still scrolling or zooming), reset timer for onRegionEndChange. 
     if ((!isTouched && !getMapCenter().equals(previousMapCenter)) || (previousZoomLevel != getZoomLevel())) { 

      // If the region has just begun changing, fire off onRegionBeginChange event. 
      if (!regionChanging) { 
       regionChanging = true; 
       if (onRegionChangedListener != null) { 
        onRegionChangedListener.onRegionBeginChange(this, previousMapCenter, previousZoomLevel); 
       } 
      } 

      // Reset timer for onRegionEndChange. 
      removeCallbacks(onRegionEndChangeTask); 
      postDelayed(onRegionEndChangeTask, changeDuration); 
     } 
    } 

    private void init() { 
     changeDuration = DURATION_DEFAULT; 
     previousMapCenter = getMapCenter(); 
     previousZoomLevel = getZoomLevel(); 
    } 

    public void setOnRegionChangedListener(OnRegionChangedListener listener) { 
     onRegionChangedListener = listener; 
    } 

    public void setChangeDuration(int duration) { 
     changeDuration = duration; 
    } 

    public interface OnRegionChangedListener { 
     public abstract void onRegionBeginChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel); 
     public abstract void onRegionEndChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel); 
    } 
} 
Cuestiones relacionadas