Google Maps en Android: seleccionar puntos en un mapa (V)

Buenas, la serie dedicada a los mapas de Google parece que nunca se acaba. Son muchas las cosas que se pueden hacer con esta api. Ya vimos como iniciar nuestro mapa, pintar puntos o incluso rutas enteras. Hoy vamos a ver como seleccionar una ubicación utilizando eventos táctiles.

Como ya vimos en otras entradas, crearemos una clase que extiende Overlay, la cual utilizabamos para pintar en ella y ahora lo haremos para manejar en ella los eventos táctiles.

La clase Overlay ya dispone de un método onTouchEvent el cual aprovecharemos y sobreescribiremos para añadir la lógica de nuestra clase.

Nuestra capa Overlay actuará entre el mapa y nuestros dedos para permitirle saber al dispositivo que punto estamos tocando y que estamos haciendo exactamente sobre él.

Para saber esto nos interesan estos eventos del MotionEvent, ACTION_DOWN, cuando pulsamos con el dedo, ACTION_UP, cuando lo levantamos y un tercero ACTION_MOVE que nos dice si nos hemos movido durante la pulsación en pantalla.

La idea es muy simple. Queremos recoger el punto del mapa cuando un usuario hace una pulsación larga sobre él. Para ello cuando pulsa con el dedo recogemos el tiempo y cuando lo levanta también, comprobamos la diferencia y si es mayor a medio segundo lo tomamos como una selección.

Hasta ahí es todo muy simple, pero hay que tener en cuenta alguna cosa. Una es que pasa si el usuario pasa mucho tiempo pulsando porque está moviendo el mapa para buscar una zona en concreto. En ese caso debemos resetear la variable con la que contamos el tiempo y no contarlo como una selección.

Otra de las cosas que puede pasar es que hagamos una pulsación larga y que no movamos el mapa, pero que lo hagamos con más de un dedo. Esto puede ser porque estamos haciendo el celebre movimiento de pellizco, con el cual podemos alejar o acercar el mapa. En este caso lo que se debe comprobar es que el número de punteros, o lo que es lo mismo, dedos, es solo uno. Con uno señalamos y con dos acercamos/alejamos. Esto lo conseguimos con getPointerCount().

Vamos a ver como queda nuestra clase:

public class MapItemizedOverlaySelect extends Overlay {

 private int LONGPRESS_TIME = 500;
 private long timeInitPress = 0;
 private long timeFinishPress = 0;
 
 private int latitud = 0;
 private int longitud = 0;

 private GeoPoint lastMapCenter;
 
 private boolean isLongPress(){
  return ((timeInitPress >= 0) && ((timeFinishPress - timeInitPress) > LONGPRESS_TIME));   
 }
 
 @Override
    public boolean onTouchEvent(MotionEvent event, MapView mapView){   
        
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
         timeInitPress = event.getEventTime();
         lastMapCenter = mapView.getMapCenter();
            GeoPoint p = mapView.getProjection().fromPixels(
                (int) event.getX(),
                (int) event.getY());
            
           
           latitud = p.getLatitudeE6();
           longitud = p.getLongitudeE6();
          
        } 
        
        if (event.getAction() == MotionEvent.ACTION_MOVE) {
         if (!mapView.getMapCenter().equals(lastMapCenter)) {
          timeInitPress = -1;          
         }
        }
        
        if (event.getAction() == MotionEvent.ACTION_UP) {
         timeFinishPress = event.getEventTime();
         if(isLongPress()){
          listenerSelectPOI.onSelectPOI(latitud, longitud);
         }
        }
        
        if (event.getPointerCount() > 1) {
         timeInitPress = -1;         
        }
        
        return false;   
    }
 
 
 public interface OnSelectPOIListener{void onSelectPOI(int Latitud, int Longitud);}
 private OnSelectPOIListener listenerSelectPOI; 
 public void setOnSelectPOIListener(OnSelectPOIListener l){listenerSelectPOI = l;}
}

Como podéis ver es muy sencillo. Controlamos el tiempo de inicio de actividad y el de fin, así como los tipos de movimiento y los números de cursores. Puede parecer mucho dicho así pero una vez en el código no lo es.

Lo último que me falta por comentar de esta clase es que hacer una vez se ha detectado que es una pulsación larga. Muy fácil. Simplemente creamos un listener que nos devolverá la latitud y la longitud y en donde utilicemos esta clase recogeremos estos valores. Luego podemos hacer lo que queramos, pintar un marcador, hacer una búsqueda sobre estos datos o lo que se os ocurra.

Vamos a ver un ejemplo muy simple de utilización de esta clase:

itemizedoverlay = new MapItemizedOverlaySelect();     
mapOverlays.add(itemizedoverlay);    
itemizedoverlay.setOnSelectPOIListener(new OnSelectPOIListener() {   
 public void onSelectPOI(int latitud, int longitud) {
  //Crear marcador, guardar en base de datos o lo que se os ocurra aquí
 }
});

Como veis, muy simple. Simplemente inicializar un objeto, añadirlo a las capas de nuestro mapa y a esperar a que el usuario haga una pulsación larga para hacer lo que vosotros necesitéis.

Comments are closed.