Creando botones de login personalizados para Android

Una de las cosas con las que menos me gusta trabajar es con los SDK de redes sociales. Cada una tiene su propia manera de hacer las cosas, por lo que a nivel de código, aún teniendo mucho cuidado, vas a terminar teniendo un batiburrillo de métodos no uniformes pero de nombres parecidos que van a ser llamados en distintos momentos y que van a trabajar de distinta forma. Pero bueno, eso quedará oculto al usuario. Lo que realmente me molesta es lo que sí se ve. Por ejemplo, los botones de login.

Captura de pantalla 2015-05-31 14.14.50

Cada empresa intenta cuidar lo más posible su imagen de marca (y esto es perfectamente comprensible). Lo que quiere cada una es que, hagas login donde lo hagas, puedas reconocer fácilmente su botón, por lo que te intentan forzar a utilizar el mismo en todas partes (ya sea iOS, Android o una aplicación Web). Y si vas a utilizar únicamente una red social, pongamos Facebook como ejemplo, esto no termina de ser malo. Aunque estés forzado a usar un determinado botón puedes ajustar el resto de tus elementos para que no termine de quedar mal. Pero lo común es que si vas a permitir que tus usuarios entren utilizando Facebook, también lo puedan hacer usando Google+ (sí, en serio), Twitter, su email o cualquier otro método que quieras contemplar.

Y terminas, cómo no, con una pantalla con varios botones de login, cada uno de su madre y de su padre. De hecho, el problema es tan estúpido que incluso aunque les pongas las mismas medidas (ancho, alto) a nivel de código, cada uno terminará teniendo unas medidas visuales diferentes porque las empresas decidieron poner unos márgenes internos y externos a sus botones, ¡sin pensar que tú los vas a querer usar junto a otros componentes! Así que terminamos jugando con las medidas para, al final, no tener algo bonito pero pasable. Botones que tienen diferentes formas, distintos márgenes, distintas fuentes y tamaños de letra… un desastre. Y si buscas por StackOverflow, en Android la solución que ha encontrado mucha gente es utilizar los botones por defecto de los SDK y cambiar sus propiedades en tiempo de ejecución, con lo que terminamos con un montón de código increíblemente complejo (obtener las medidas de la pantalla en pixeles para transformarlas a dp para calcular un porcentaje de transformación para aplicarlo a una vista que hemos encontrado navegando entre las vistas hijas del botón para después forzar que se dibuje de nuevo) y, por lo tanto, poco mantenible.

Figura 1: el antes y el después

Figura 1: el antes y el después

El objetivo de hoy: hacer unos botones personalizados para que nuestros usuarios puedan hacer login con Facebook y con Google+ (pero que se puedan modificar fácilmente para entrar con cualquier red social).

En la Figura 1 se están utilizando, en la parte superior, los botones stock de los SDK de Facebook y de Google respectivamente. El de Google tiene el texto cambiando mediante un snippet de código que busca el TextView correspondiente navegando entre las vistas hijo del botón, para que coincidiese con el de Facebook. Mediante código el botón de Facebook tiene un ancho superior al de Google+, a pesar de que en la imagen parezcan iguales, para que cuadrasen los anchos. Por mucho que lo intenté, los altos no coinciden (ya que no permitían ser modificados *aplausos*).

Los botones de la parte inferior de la Figura 1 comparten el mismo código. Sólo cambian los colores, el texto y el source de la imagen. Son puro XML y constan de dos elementos. Un LinearLayout horizontal (ImageView | View | TextView) y un Selector para que el color de fondo cambie según el estado del botón (por defecto, selected, focused) y tengan padding interno y esquinas redondeadas. De hecho, al principio del párrafo os he mentido. Ni si quiera son botones (Vistas Button de Android), sino que están metidos en el layout padre mediante el elemento <include>.

Lo primero que vamos a elaborar es el Selector. Nuestro selector se compondrá de tres items, que serán seleccionados según el estado que le indiquemos a cada uno. Hay que tener en cuenta que Android recorrerá el selector de manera secuencial y se quedará con el primer item que se ajuste al estado, por lo que, teniendo en cuenta que hay unos estados más específicos que otros, hay que definirlos en el orden correcto. De todas formas, si no lo hacemos bien, Android Studio nos avisará de que habrá items no alcanzables (y hay locos por el mundo que siguen usando Eclipse con el ADT plugin…).

Para cada item, definiremos una Shape que constará, a su vez, de tres elementos. Un Solid (que será el color que rellenará la shape), un Padding, que será la separación interna de los elementos respecto al borde, y un Corners, en el que indicaremos el radio de curvatura de las esquinas.

Por supuesto, la mejor práctica sería sacar todos esos colores hexadecimales a otro fichero colors.xml, y todas las dimensiones repetidas (márgenes y radio de las esquinas) a dimens.xml, para poder modificar todos los valores al mismo tiempo. Lo dejo tal cuál en el fichero por no incluir gists del resto de recursos.

El siguiente paso es hacer el layout del botón. Se compondrá de un LinearLayout horizontal, que tendrá dos vistas hijas. El primer elemento (que se alineará, por lo tanto, a la izquierda) será un RelativeLayout con un ancho fijo de 50dp y una altura que se ajuste al padre (posteriormente el botón medirá 50dp de alto, por lo que el ancho de este RelativeLayout no es al azar). El segundo elemento será una TextView que se alineará al centro tanto vertical como horizontalmente. En el RelativeLayout incluiremos dos elementos. Una ImageView, que será el logo de la red social, una View (tal cual) que, con un buen color de fondo, servirá de separador.

Como veis, el LinearLayout tiene como fondo el selector creado antes. Además, le indicamos que el usuario va a poder hacer click sobre él. Si este atributo no estuviese seteado a true, el botón no proporcionaría ningún tipo de feedback visual cuando el usuario lo pulsase (haciendo del selector algo completamente inútil).

El logo de Facebook lo he sacado de la web Facebook brand assests y lo he redimensionado a 24dp usando el siempre útil Android Assets Studio.

Ahora nuestro botón luce tal que así.

Figura 2: el botón de login por separado.

Figura 2: el botón de login por separado.

Como se puede apreciar, el separador, a pesar de no tener ningún margen, no llega hasta el final ni por arriba ni por abajo. Esto es gracias al padding del selector, que nos evita tener que preocuparnos por él después en el propio botón. Si quisiésemos dar la responsabilidad del padding al propio Layout del botón, el atributo de padding se lo daríamos al LinearLayout.

Otra cosa que quiero señalar es el truco del separador. Dándole a una View de ancho 1dp un color de fondo ligeramente más oscuro que el resto, tenemos una manera muy muy sencilla de mejorar notablemente el resultado final sin liarnos con ImageViews pasadas por 9patch. Además, en este caso el separador no es simplemente para que los botones queden bonitos. En la Figura 1 se aprecia que el de Facebook no lo tiene, pero el de Google+ sí. Es un requisito que está en el dossier de imagen de marca de Google, y siendo ellos los que aprueban las aplicaciones de Play Store, prefiero ajustarme a su branding antes que al de Facebook.

Ahora lo único que queda es hacer otro botón para Google+ exactamente igual. Cambiaremos, por supuesto: el logo, el texto y los colores de separador y selector. Una vez lo tengamos, queda incluir el monstruoso layout de la Figura 2 en otro de forma que se vea decentemente. ¿Cómo? Pues de una manera realmente sencilla.

Gracias al tag <include> podremos reutilizar los botones creados donde sea necesario.

Deja un comentario