domingo, 26 de octubre de 2014

Pestañas en Android



En apartados anteriores hemos visto como dar forma a la interfaz de usuario de nuestra aplicación mediante el uso de diversos tipos de layouts, como por ejemplo los lineales, absolutos, relativos, u otros más elaborados como los de tipo lista o tabla. Éstos van a ser siempre los elementos organizativos básicos de nuestra interfaz, pero sin embargo, dado el poco espacio con el que contamos en las pantallas de muchos dispositivos, o simplemente por cuestiones de organización, a veces es necesario/interesante dividir nuestros controles en varias pantallas. Y una de las formas clásicas de conseguir esto consiste en la distribución de los elementos por pestañas o tabs. Android por supuesto permite utilizar este tipo de interfaces, aunque lo hace de una forma un tanto peculiar, ya que la implementación no va a depender de un sólo elemento sino de varios, que además deben estar distribuidos y estructurados de una forma determinada nada arbitraria.

Adicionalmente no nos bastará simplemente con definir la interfaz en XML como hemos hecho en otras ocasiones, sino que también necesitaremos completar el conjunto con algunas líneas de código. Desarrollemos esto poco a poco.

En Android, el elemento principal de un conjunto de pestañas será el control TabHost. Éste va a ser el contenedor principal de nuestro conjunto de pestañas y deberá tener obligatoriamente como id el valor "@ android:id/tabhost". Dentro de éste vamos a incluir un LinearLayout que nos servirá para distribuir verticalmente las secciones principales del layout: la sección de pestañas en la parte superior y la sección de contenido en la parte inferior. La sección de pestañas se representará mediante un elemento TabWidget, que deberá tener como id el valor "@android:id/tabs", y como contenedor para el contenido de las pestañas añadiremos un FrameLayout con el id obligatorio "@android:id/tabcontent".

Por último, dentro del FrameLayout incluiremos el contenido de cada pestaña, normalmente cada uno dentro de su propio layout principal (en mi caso he utilizado LinearLayout) y con un id único que nos permita posteriormente hacer referencia a ellos fácilmente (en mi caso he utilizado por ejemplo los ids "tab1", "tab2",…). A continuación represento de forma gráfica toda la estructura descrita.


Si traducimos esta estructura a nuestro fichero de layout XML tendríamos lo siguiente:


Como podéis ver, como contenido de las pestañas tan sólo he añadido por simplicidad una etiqueta de texto con el texto "Contenido Tab NºTab". Esto nos permitirá ver que el conjunto de pestañas funcionacorrectamente cuando ejecutemos la aplicación.

Con esto ya tendríamos montada toda la estructura de controles necesaria para nuestra interfaz de pestañas.
Sin embargo, como ya dijimos al principio del apartado, con esto no es suficiente. Necesitamos asociar de alguna forma cada pestaña con su contenido, de forma que el control se comporte correctamente cuando cambiamos de pestaña. Y esto tendremos que hacerlo mediante código en nuestra actividad principal.

Empezaremos obteniendo una referencia al control principal TabHost y preparándolo para su configuración llamando a su método setup(). Tras esto, crearemos un objeto de tipo TabSpec para cada una de las pestañas que queramos añadir mediante el método newTabSpec(), al que pasaremos como parámetro una etiqueta identificativa de la pestaña (en mi caso de ejemplo "mitab1", "mitab2", …).
Además, también le asignaremos el layout de contenido correspondiente a la pestaña llamando al método setContent(), e indicaremos el texto y el icono que queremos mostrar en la pestaña mediante el método setIndicator(texto, icono). Veamos el código completo :


Si vemos el código, vemos por ejemplo como para la primera pestaña creamos un objeto TabSpec con la etiqueta "mitab1", le asignamos como contenido uno de los LinearLayout que incluimos en la sección de contenido (en este caso R.id.tab1) y finalmente le asignamos el texto "TAB1" y el icono android.R.drawable.ic_btn_speak_now (Éste es un icono incluido con la propia plataforma Android. Si no existiera en vuestra versión podéis sustituirlo por cualquier otro icono). Finalmente añadimos la nueva pestaña al control mediante el método addTab().

Si ejecutamos ahora la aplicación tendremos algo como lo que muestra la siguiente imagen, donde podremos cambiar de pestaña y comprobar cómo se muestra correctamente el contenido de la misma.

Lo muestro tanto para Android 2.x como para Android 4.x




Una pequeña sorpresa. Como podéis comprobar, aunque estamos indicando en todos los casos un texto y un icono para cada pestaña, el comportamiento difiere entre las distintas versiones de Android. En Android 4, el comportamiento por defecto del control TabHost es mostrar sólo el texto, o solo el icono, pero no ambos. Si eliminamos el texto de la primera pestaña y volvemos a ejecutar veremos como el icono sí aparece.

 
Con la pequeña modificación anterior la aplicación se vería así: 


En cuanto a los eventos disponibles del control TabHost, aunque no suele ser necesario capturarlos, podemos ver a modo de ejemplo el más interesante de ellos, OnTabChanged, que se lanza cada vez que se cambia de pestaña y que nos informa de la nueva pestaña visualizada. Este evento podemos implementarlo y asignarlo mediante el método setOnTabChangedListener() de la siguiente forma: 



En el método onTabChanged() recibimos como parámetro la etiqueta identificativa de la pestaña (no su ID), que debimos asignar cuando creamos su objeto TabSpec correspondiente. Para este ejemplo, lo único que haremos al detectar un cambio de pestaña será escribir en el log de la aplicación un mensaje informativo con la etiqueta de la nueva pestaña visualizada. Así por ejemplo, al cambiar a la segunda pestaña recibiremos el mensaje de log: "Pulsada pestaña: mitab2".


Saludos compañeros, aprovechen la información.








No hay comentarios:

Publicar un comentario en la entrada