¡Atención! Este sitio utiliza cookies.
Si no cambias la configuración de tu navegador, aceptas su uso.

Manejo de interfaces de usuario en Android para desarrolladores de Cocoa

Saber manejar eventos de la interfaz de usuario y asignar propiedades a las vistas es algo bastante sencillo de hacer en Android, pero si eres desarrollador de Cocoa —o nunca has programado este tipo de cosas en Java—, dado que nos encontramos en otro entorno y otro lenguaje, es posible que la forma de hacerlo nos parezca un poco extraterrestre.

Este artículo está íntimamente relacionado con otros en este blog, pero dado que están más centrados en la arquitectura de la app, no se ha profundizado en ello. Si encuentras dificultades, puedes referirte a ellos:

UIKit vs Android

Como sabrás, UIKit es el framework dedicado a las aplicaciones móviles de Apple, dentro de Cocoa, y por ello Android es su competidor más directo. Ambos funcionan con paradigmas algo diferentes en todas sus capas, empezando por la más profunda –partiendo del lenguaje–, y conforme vamos subiendo, van tornándose más marcianas, hasta el punto en que esté totalmente justificado que cualquier app nativa tenga una implementación propia y dedicada (aunque estén escritas en precioso C#). La parte del manejo de vistas es claramente uno de los aspectos más divergentes de ambas tecnologías.

Patrón ‘Target-Action’ de UIKit

El ‘Target-Action’ es un patrón de diseño en el cual un objeto retiene la información necesaria que deberá enviar a otro cuando se cumpla cierto evento. Este paquete de información consta de dos partes: quién ha de recibir este mensaje (Target), y qué instrucción debe ejecutar (Action) cuando lo haga. Es lo que utilizamos en UIKit para manejar los eventos que ocurren en la capa de las vistas (cuando tocas un botón, deslizas el dedo sobre la pantalla, haces zoom con los dedos…). Cuando una vista es molestada, despierta al target que tiene asignado (que será un controlador), y le dice qué es lo que ha pasado (“el cateto este acaba de ponerme todo el dedaco encima y lo acaba de levantar”).

De esta forma, dentro del controlador es donde realizamos realmente las acciones que nos llegan de las vistas. Normalmente lo hacemos a través de IBActions, que son enlaces que sabe manejar Xcode entre el código del controlador y las vistas. A nosotros nos vale prácticamente con pinchar en una vista y arrastrar hasta el código para que ¡plop!, tengamos su función lista para implementar.

‘Listeners’ en Android.

Es un patrón de comportamiento en el cual un objeto queda “a la escucha” de posibles cambios de estado en otro objeto. Es muy típica en Java. La idea es capturar qué le ha ocurrido exactamente a un objeto cuando se ve alterado. En el caso de Android, de la vista con la que ha interactuado el usuario. Estos event listeners son interfaces ‘precocinadas’ y proporcionadas por la clase View para acceder de forma directa a estos eventos. Si, por ejemplo, el cateto tocase sobre un botón, el método onTouchEvent() se invocaría, puesto que había una escucha ante tal cambio.

Si ya conocías el patrón de diseño del Observer, esto en la práctica es lo mismo pero con otro nombre. El fabricante que no le pone su nombre a algo ya inventado es porque se le ha olvidado.

Y los ‘Event Handlers’.

Un ‘event handler’ es realmente lo que está tras las bambalinas cuando recibimos un evento de un listener. Están en contacto directo con el objeto que las recibe. Es decir, no es tarea de un controlador externo interceptarlos, sino de la propia vista. Por ejemplo, un botón recibiría un evento tipo “toque realizado sobre el cuadrante en el que has ido dibujado”. Sería tarea de este mandar otro al interesado, una vez haya descubierto qué tipo de toque ha recibido, y sería, ahora sí, uno para cualquier listener. Esto es como cuando tu madre murmura “hay que sacar la basura”. Inmediatamente pega el grito “fulanito –o sea, tú— ¡SACA LA BASURA!”. Uno reconoce un cambio de estado, pero es otro quien realiza una acción al respecto.

Por eso, un objeto debe tener un event handler determinado para cada evento, pero puede tener tantos event listeners como se le puedan añadir, ya que el patrón del listener es del tipo 1 a N acosadores, mientras que el que nos ocupa ahora mismo es 1:1 (solo hay una persona en tu casa que se da cuenta de que hay que tirar la basura, y lo sabes).

¿Cuál usar?

Por norma general, solo implementamos estos event handlers cuando creamos subclases de vistas, para hacer algo más chulo y específico con ellas. Si estamos usando controles estándar, con los event listeners nos basta.

¡Enséñame el código!

Ya en materia de código, existen varias formas de implementar los eventos. Haré dos ejemplos con onClick, que por cierto en Android no representa un clic, sino un tap.

Crear una clase privada para manejar un evento para un determinado objeto

En Java es posible —y bastante habitual además— crear clases privadas dentro de unas ya existentes. Es decir, declarar una clase dentro de nuestro controlador, y que esta ‘encapsule’ la funcionalidad de los eventos que reciba de un determinado objeto.

OnClickListener es una interfaz interna dentro de la clase View, la cual contiene el método onClick(View v).

Ventajas

Al haber asignado una clase a una vista en particular, podemos tener la absoluta certeza de qué control envió un evento concreto. Nos ahorra el tener que preguntar por la vista que lanzó el evento por ejemplo (imagina que tuviéramos dos botones).

Inconvenientes

Quizá sea un poco engorroso si tenemos varios eventos y varios objetos a observar…

Implementar la interfaz onClickListener

Declarar una interfaz nos obliga a cumplir ciertas instrucciones en nuestro código. Es la forma de eludir la herencia múltiple en Java (o abrazarla, según se mire). Al implementar OnClickListener el compilador nos obligará a sobrescribir el método public void onClick(View v), lo que quiere decir que, como decimos que estamos capacitados para responder a esos mensajes métodos, los ‘capturaremos’ ahí.

Lo único que queda es agarrar una vista que acepte este tipo de eventos y asignarle el de onClickListener (en este caso). Nos pedirá por parámetro el objeto que debe responder al método. Pasamos generalmente this porque es la propia clase la que lo hace (el Activity o Fragment en el que estamos).

Dentro del método onClick tendremos que preguntar por la vista que lo ha lanzado. Si tuviésemos varias vistas de las que quisiéramos responder a toques, nos saltarían todos, así que tenemos que hacer una pequeña criba antes de ponernos manos a la masa. Simplemente preguntamos si coinciden los ID, ningún misterio.

Ventajas

Podemos centralizar todos los eventos similares dentro de un solo método.

Inconvenientes

Puede que en determinados casos pueda ser engorroso preguntar por la vista que ha mandado el evento si tenemos muchas.

 

Asignación de propiedades a vistas

Así como en UIKit utilizamos los IBOutlets, esos “enganches” que nos facilita Xcode para enlazar vistas directamente a un controlador en tiempo de diseño, en la plataforma del androide no existe tal facilidad. Eres tú quien debe conocer la referencia a ellas y crear una referencia a la instancia en tiempo de ejecución.

Acceso a vistas en Android

La instancia ya existe en la mayoría de los casos (el robot verde se encarga de ‘inflarlas’ por nosotros), es solo que el IDE no nos ha facilitado otro modo de apuntar a ellas que el ID de las mismas.

Para recuperar la referencia a una vista ya compilada (tiene que estar en el archivo de recursos) se utiliza el método findViewById presente en todos los Activities. A este método se le está pasando realmente una referencia como número entero.

Dado que Java no es un lenguaje dinámico, no tenemos otra opción que hacer un casting del objeto que recuperamos del método findViewById simplemente para que nos compile. Nos obliga a saber qué tipo de vista vamos a recuperar en tiempo de compilación. Este es el tipo de cosas que se echa de menos de los lenguajes dinámicos, pero en fin… Te hacen apuntar a las vistas en tiempo de ejecución, pero te fuerzan a saber su tipo en tiempo de compilación. Me encanta bailar mientras me apuntan con una pistola.

Mejor lo dejamos ahí.

Cualquier corrección, añadido, o pregunta, házmelo saber en los comentarios. Soy consciente de que no he cubierto todos los flecos (¿gestos?). Si crees que sería bueno profundizar en algún concepto en concreto, me encantará hacerlo.

¡Muchas gracias!

Escrito por Miguel Hernández Jaso

Autor del blog. Desarrollador especializado en iOS.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Mi Gobierno me obliga a decirle que utilizo 'cookies' en mi página. Si continúa navegando, quiere decir que está conforme con ello.