«

»

sep 03 2012

MapViews 2: Globos de información

 
Visto el éxito que tuvo mi primera entrada sobre MapViews, y los recientes tutoriales sobre Osmdroid del compañero JMPergar, me veo en la obligación de continuar extendiéndome un poco más con el uso de mapas en nuestras aplicaciones. En esta ocasión voy a contaros cómo mostrar globos de información al pulsar un punto del mapa, al igual que hacen muchas aplicaciones como el propio Google Maps.

Partiremos de la base del anterior tutorial con un mapa creado y mostrando puntos en él. Así que asumiré que sabéis y entendéis cómo funciona lo que vimos entonces.

 

La idea básica

La idea es realmente sencilla: en el evento onTap() que usábamos para detectar pulsaciones sobre un marcador, lo que haremos será crear una nueva View correspondiente al globo, centrada en la posición del marcador, y que pueda detectar pulsaciones sobre ella misma. Pero no os preocupéis, tenemos disponible una magnífica librería de Jeff Gilfelt que nos facilita aún más esta tarea: android-mapviewballoons. Nos descargamos el código y lo importamos como proyecto-librería en el nuestro. También os aconsejo que echéis un ojo al proyecto de ejemplo que viene con la librería y demuestra cómo usar todas sus características.

 

Implementación

Una vez listos empecemos con el código, que es bastante sencillo. Si recordáis en el anterior tutorial creábamos una clase, que yo llamé MyItemizedOverlay, y que extendía a ItemizedOverlay<OverlayItem>. Pues para usar globos es tan simple como modificar esta clase propia para que extienda a BallonItemizedOverlay. Ésta superclase se encarga de gestionar todo el proceso por nosotros. También debemos añadir a los parámetros del constructor un MapView, y cambiar el método onTap() que implementamos nosotros por onBallonTap(). Ésto es porque la clase BallonItemizedOverlay ya implementa el onTap, pues es donde se encarga de mostrar el globo, en cambio el método onBallonTap() será el que se ejecute al pulsar encima del globo de información. Fácil, ¿eh?

 

public class MyItemizedOverlay extends BalloonItemizedOverlay<OverlayItem> {
    private List<OverlayItem> mOverlays;
    private Context mContext;

    public MyItemizedOverlay(Drawable defaultMarker,Context context, MapView mapView) {
        super(boundCenter(defaultMarker), mapView);
        mOverlays = new ArrayList<OverlayItem>();
        mContext = context; //o mContext = mapView.getContext();
    }

	@Override
    protected OverlayItem createItem(int index) {
        return mOverlays.get(index);
    }

    @Override
    public int size() {
        return mOverlays.size();
    }

	@Override
	public boolean onBalloonTap(int index, OverlayItem item){
		// Hacemos lo que queramos hacer cuando el usuario pulse el
		// globo correspondiente al "item" número "index"
	}

}

 

Y… ¡eso es todo! Con esto ya tenemos montados nuestros globos. La información mostrada corresponde a los parámetros title y snippet usados al crear los objetos OverlayItem.

 

 

¿No has tenido bastante? Pues sigue leyendo.

 

Personalización

Habrá casos en que no nos valdrá con el globo que nos muestra la librería, sino que queramos personalizar un poco su apariencia. Colores, disposición de contenidos, otro tipo de información…

La librería nos permite algunos ajustes en los globos por defecto. Podemos des/activar el botón de cerrar globo, una flecha a la derecha al estilo de Google Maps, o la opción de centrar el mapa en el marcador al abrir el globo. Esto es con los métodos de BalloonItemizedOverlay setShowClose()setShowDisclosure()setSnapToCenter() que llamaremos donde creemos nuestras capas, normalmente en el MapActivity. Sus valores por defecto son true, false y true respectivamente. (Para mostrar la flecha hay que desactivar explícitamente el botón cerrar).

 

MyItemizedOverlay markers = new MyItemizedOverlay(drawable, this, mapView);
markers.setShowClose(false);
markers.setShowDisclosure(true);
markers.setSnapToCenter(true);
// ... añadir objetos al Overlay ...

 

Globo propio

Además de las opciones de uso común anteriores, podemos usar globos totalmente personalizados con nuestro propio layout. Todo lo que hay que hacer es sobreescribir el método createBalloonOverlayView() de BalloonItemizedOverlay para devolver una subclase de BalloonOverlayView que creamos nosotros, y cuyo método setupView() sobreescribimos para crear nuestra View personalizada, así como el método setBalloonData() para colocar la información del Item en cada componente. Éste tipo de globo es algo más complejo, pero se entiende bien echando un vistazo al ejemplo.

 

Extra

Ya que estamos con la librería aprovecho para aconsejaros una característica extra que trae. Se trata de la clase TapControlledMapView, una extensión de MapView hecha por el autor que le añade algunas funcionalidades, como el doble tap para hacer zoom y un tap (en un espacio libre) para cerrar el globo abierto. Es tan sencillo como usar la clase TapControlledMapView en nuestro código en vez de MapView, y el componente <com.readystatesoftware.maps.TapControlledMapView … /> en el layout XML.

Espero que os sea de utilidad. Cualquier duda a los comentarios. ¡Hasta la próxima!
 

Acerca del autor

Rafa Vázquez

Estudio Ingeniería Informática del Software en Sevilla. Me considero geek sin dinero, amante y desarrollador novato de Android. He creado algunas aplicaciones como SeviBus, TicTacDroide, Kill Bieber y Traductor Hoygan, si es que se puede llamar aplicaciones a estas dos últimas ;) Ganas de aprender más y más no me faltan, e intentaré compartir mis experiencias con vosotros en la medida de lo posible.

  • Ivan

    Hola,

    Estoy implementando la libreria de de este articulo y todo me funciona correcto excepto los tab encima de los balones. El codigo que tengo puesto en la clase MyItemizedOverlay es el siguiente:

    //@Override
    public boolean onBallonTap(int index, OverlayItem item) {
    Toast toastaa = Toast.makeText(mContext, “movido” , Toast.LENGTH_SHORT);
    toastaa.show();
    return false;
    }

  • Ivan

    Hola,

    Estoy implementando la libreria de de este articulo y todo me funciona correcto excepto los tab encima de los balones. El codigo que tengo puesto en la clase MyItemizedOverlay es el siguiente:

    //@Override
    public boolean onBallonTap(int index, OverlayItem item) {
    Toast toastaa = Toast.makeText(mContext, “movido” , Toast.LENGTH_SHORT);
    toastaa.show();
    return false;
    }

    El Override lo tengo que tener comentado porque el eclipse no me deja si no compilar el programa, ya que me dice que es erroneo.

    ¿Cual puede ser el problema?

    Aparte el metodo setShowDisclosure(true/false) no logro saber que hace. ¿Que cambios realiza en los globos?

    Gracias.

    Un saludo!

    • http://about.me/sloy Sloy

      Si tienes que comentar el Override es que tu problema es más grave. Quizás estás usando sin querer una versión anterior de Java para compilar, a mi me ha ocurrido varias veces. Comprueba las propiedades del proyecto.

  • Nacho

    No puedo importar la librería externa para los globos.
    Sigo las instrucciones de este enlace:
    http://developer.android.com/intl/es/tools/projects/projects-eclipse.html#ReferencingLibraryProject
    pero en el cuadro de diálogo donde tengo que seleccionar la librería no me aparece ninguna.
    Dice algo de que tengo que tener la librería en el workspace al igual que el proyecto, pero…¿a qué se refiere con esto? ¿A qué dentro de workspace tengo que copiar la carpeta de la librería que me descargo? …

    Gracias por tu atención.

    • http://about.me/sloy Sloy

      Un “library project” es un proyecto en tu workspace, marcado como librería para que otros proyectos Android puedan “importarlo”.
      Tienes que añadir la librería de los globos como un proyecto más a tu workspace, entonces te aparecerá en ese cuadro de diálogo.

      • Nacho

        De acuerdo muchas gracias Sloy, pero cuando finalice la aplicación y en el caso de que fuera publicada en el Market, ¿esa librería ya estaría importada dentro de mi propia aplicación no? Es decir, cuando un usuario instale mi aplicación, instala entonces también esa librería ¿no es así?

        Saludos.

        • http://about.me/sloy Sloy

          Por supuesto. En el APK compilado se encuentra todo lo necesario, incluídas las librerías. De cara al compilador, las “library project” funcionan igual que un jar

          • Nacho

            OK perfecto, muchas gracias.
            Una última cosilla, ¿me recomiendas seguir desarrollando los mapas de mi aplicación con esta API o es preferible cambiar todo ahora que estoy a tiempo y desarrollar con la nueva API de Google Mapas v2 empleando MapFragment? Por lo visto, simplifica mucho las cosas…

            Gracias de nuevo crack.

          • http://about.me/sloy Sloy

            Pues sinceramente te recomiendo que intentes desarrollarla con la v2. Algunas cosas las facilita y otras las complica, pero es un buen salto de calidad en los mapas. Además, la API v1 está obsoleta, a partir del 18 de marzo dejarán de expedir nuevas keys para usar los mapas (aunque seguirán funcionando las existentes).