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

Layouts en Android para desarrolladores de Cocoa

Aunque mis andanzas suelen llevarme normalmente por el camino del bien, también a veces tengo que desviarme y tomar la senda de Android, lo que me lleva a ampliar conocimiento y por ende, a aprender a hacer las cosas de forma diferente a la acostumbrada; esto es, a comparar. Como desarrollador de Cocoa, mi forma de distribuir los elementos visuales (crear la interfaz) de una aplicación es bien diferente a otras, como puede ser el siempre desquiciante uso de CSS, o los layouts de Microsoft con XAMLs, o los de Android, como viene a ser el caso. Encuentro ventajas e inconvenientes respecto al AutoLayout de Apple, como en todo, pero sobre todo una forma de enfrentarse al diseño muy diferente, ya que en según qué casos, uno u otro sistema favorecen un tipo de interacción y disposición de elementos más flexible o más rígida.

Explorando los diferentes caminos de la Fuerza

Para los que somos más iniciados en el mundo del androide y, sobre todo, los que venimos de la manzana (en Windows Phone no es radical la diferencia), pretendo que este artículo me sirva de guía a mí y a todos los que no acostumbran a pisar el lado oscuro y necesitan documentación de referencia rápida desde un punto de vista práctico, ya que hay muchas guías en Internet sobre el tema, pero no tantas comparando este mundo con los de AutoLayout (AL para abreviar).

Android Layouts

Propiedades de ancho y alto (layout_width y layout_height)

Match Parent

Establece que la vista ‘encajará’ o se ‘estirará’ hasta con dar con el tamaño de su supervista, similar a asignar el Top y Bottom Layout Guide, y los Leading y Trailing space a 0, aunque no igual.

Fill Parent (obsoleto)

La vista se agrandará hasta tomar el tamaño de la supervista, al igual que MatchParent (es lo mismo con otro nombre). No se usa desde la API 8 (es decir, nunca), ya que el nombre llevaba a confusión por dar a entender que rellenaba espacios en blanco cuando no es así (para eso se utiliza weight, que veremos ahora).

Wrap Content

La vista tendrá el tamaño requerido para mostrar todo su contenido y en ningún caso tratará de rellenar espacios en blanco. En el caso de AL, similar al tratamiento que suelen tener las etiquetas por defecto (sizeToFit).

Propiedad de compresión (layout_weight)

La propiedad layout_weight especifica la importancia de una vista con respecto a sus vecinas. Tiene un efecto similar a los hugging y compression priorities de AutoLayout, en cuanto a que, en caso de tener dos vistas compartiendo espacio, podemos dar a una más prioridad que a otra a la hora de expandirse, o de encojerse y apretarse para rellenar el espacio sobrante.

¿Cómo funciona en Android? Asignamos un número (peso) a cada vista, el cual determina a cuántos bloques equivale con respecto a la otra. Es decir, dadas dos etiquetas a la par, si a una le asignamos 1 («Hola») y a la otra 2 («Mundo»), la primera llenaría unas tres cuartas partes del ancho ya que la segunda ocuparía una proporción de 1 a 2. Si «Mundo» tiene un peso 3 y mantenemos el de «Hola» a 1, veremos que «Mundo» encoge todavía más, ya que su ‘peso’ en la distribución es una tercera parte que «Hola». A mayor peso, más encoge una vista (aunque suene al revés), ya que el peso no equivale a la fuerza de expansión de una vista, sino a cuántas veces necesita repetirse para pesar tanto como otra.

Dicho de otra forma, si Falete tiene peso 1, yo tendría peso 200, más o menos (y justo después de almorzar) si estuviéramos en el mismo ascensor (y suponiendo que el ascensor sea capaz de subirnos). ¿Por qué? Porque yo estaría escachurrado contra una esquina para hacer sitio al «Magnánimo».

Evidentemente, si dos vistas tienen el mismo peso, sea el que sea, ocuparán lo mismo, y en este caso se dividirían el ancho en un 50%, ya que de ser 2 la relación sería 2:2, que es 1:1. Esto en AL es lo que conseguiríamos con equalWidth entre dos vistas, siempre y cuando su margen horizontal fuera el mismo.

Como una imagen vale más que mil palabras y a mí ya se me está acabando el espacio de alojamiento en el servidor, voy a ilustrarlo con tres sencillos ejemplos:

Weight

Tipos de Layouts

FrameLayout

Es el más sencillo. Ancla los elementos a la esquina superior izquierda, de forma similar a como lo haría en CSS un «position: absolute» con coordenadas 0,0. Esto quiere decir que, generalmente, es solamente útil cuando queremos mostrar un único elemento en esta posición, ya que el resto se superpondrán.

FrameLayout

RelativeLayout

Si consideramos una sucesión de vistas colocadas en referencia a una anterior (por ejemplo, una caja de texto y dos botones debajo, uno a la par del otro, alineadas a la izquierda), pero siempre haciendo referencia a otra cercana), nos podremos servir de la distribución relativa. Esto sí que recuerda mucho más a AutoLayout, ¿verdad? Salvo aquellas que van ancladas a la supervista, el resto siempre toman como referencia a otra ya existente para colocarse. En el caso de Android es más similar al diseño con CSS, ya que en el fondo todas las vistas van una junto a la otra y la manera de crear espacio negativo es utilizando márgenes de forma específica, con la propiedad layout_margin en este caso.

Como la documentación sobre la relación entre vistas es extensa, prefiero hacer referencia a la fuente, donde vienen todos los tipos de relaciones listados, en la web oficial de desarrollo de Android.

RelativeLayout

Este es el layout que querrás utilizar cuando quieras que una vista esté justo debajo de otra, que esté anclada al pie de su contenedor, que los bordes estén alineados con otra vista vecina, etc.

 LinearLayout

Es el layout más recurrente y al menos para mí más interesante. Los que desarrollamos con Xcode antes solo llegábamos a rozar el potencial de este sistema en las tablas estáticas disponibles en los Storyboards. Pero no son, ni por asomo, sustitutas de LinearLayout.

Actualización: Por fin en iOS tenemos algo similar, disponible en Xcode 7 y compatible a partir de iOS9, llamado StackView. Soluciona papeletas de AL, de modo que no está pensado para utilizarse extensivamente sino para evitar complejidad innecesaria.

LinearLayout

Las pantallas de Android no se distribuyen en cuanto a posiciones fijas dentro de un canvas finito (o como me gusta decir a mí, «deseadas», ya que las definiciones en AL son declarativas), sino que van colocándose una detrás de otra, a modo de tabla, de modo similar a utilizar la propiedad «position:relative» sobre todas las etiquetas contenedoras de CSS, o incluso «display:table» si me apuras. Esta técnica permite, entre otras cosas, olvidarnos de a cuánta distancia está un elemento de otro, o de disminuir su altura para ‘liberar’ espacio vertical. En el fondo, estamos tratando con una tabla, y por tanto todas las vistas hijas actúan como filas (o celdas, según se vea) dentro de ella.

Existen dos tipos de LinearLayout:

  • Horizontal: las vistas se colocan una detrás de la otra al mismo nivel.
  • Vertical: las vistas cuelgan en sucesión, a modo de persiana.

Si ya tienes un poco de experiencia en desarrollar con WatchKit, seguro  que todo esto te resultará muy familiar.

Grid Layout (disponible a partir de la API 14, ‘Ice Cream Sandwich’ o algo así)

Nos permite distribuir las vistas en una rejilla rectangular, pero no como filas y columnas, sino como celdas, como una tabla de Excel (o como la cuadrícula de hundir la flota si la palabra ‘Excel’ te da migraña como a mí). La disposición establece propiedades como el espaciado entre celdas, y la disposición y alineación de las filas o columnas (centrado, a la izquierda…).  Todo cuanto conozcas de UICollectionView te será familiar, solo que en este caso no estamos hablando de una vista como tal, sino de una disposición de varias de ellas. Es decir, no confundas GridLayout con GridView, que sí es el equivalente a nuestra amada UICollectionView.

Es perfecto para los menús de la HomeActivityMainActivity.

GridLayout

TableLayout

Entendida GridLayout, solo queda apuntar que esta funciona de forma similar, solo que en esta distribución en concreto solo trabajamos con filas y sus columnas, similar a una tabla en HTML. No hay que confundir este TableLayout con ListView, aunque sus diferencias son evidentes.

Las filas se suceden con una altura fija, o determinada por sus vistas hijas si establecemos la altura como Wrap_Content.TableLayout

Las columnas tienen el ancho de la más ancha dentro de la misma fila (aunque es posible sobrescribir este comportamiento con setColumnShirnkable() o setColumnStretchable(), o si queremos eliminarla con setColumnCollapsed(). Sí, a estos javeros les encantan las cosas con paréntesis vacíos e inútiles, qué le vamos a hacer.

El cuándo utilizar TableLayout o GridLayout depende de dónde y cuándo queremos especificar el número de filas o columnas, ya que la distribución en forma de tabla se crea de forma estática, mientras que con la rejilla podemos especificar el número de filas, columnas y el tamaño de las celdas puede decidirse en tiempo de ejecución. El grid es más flexible, ya que solo con colocar una sucesión de vistas seguidas dentro de él, sin especificar fila, podemos alterar su apariencia según los distintos tamaños de pantalla.

 

 Concluyendo

El sistema de Android es, en mi opinión, más sencillo y fácil de aplicar que en iOS, ya que funciona sobre plantillas predeterminadas y tiene menos conceptos que aprender. Muchas, pero ya establecidas. El sistema va a ocuparse de colocar casi siempre todos los elementos en sucesión de alguna forma. Cambiar de pantalla siempre alterará un diseño inicial, pero normalmente respetará las proporciones (aunque con las resoluciones altas casi me retracto de decir esto). Yo me quedo con AutoLayout, casi más por costumbre y comodidad que por beneficio tengo que admitir, pero sobre todo ahora, teniendo a la vista las interfaces de WatchKit, me parece una decisión muy acertada apostar por este sistema en el que no importa el centro de la pantalla tanto como la parte superior. Ojalá pudiéramos decir adiós a las ScrollView que tantos dolores de cabeza dan a veces: que la pantalla crezca lo que tenga que crecer según su número de elementos y la altura de estos.

Y recuerda, por muchos nombrecitos de dulces que ponga Google a las versiones de Android, no hay nada mejor que una taza de chocolate con unos churros. Que nadie se engañe, que detrás de esto todavía siguen tomando café de sobre. Sin rencores.

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.