Una limitación que a veces encontramos al utilizar un layout en Android es la imposibilidad de definir dimensiones relativas mediante porcentajes. Siempre podemos implementar nuestro propio layout pero la estrategia más habitual suele ser utilizar LinearLayout y el atributo layout_weight tal y como se muestra en el tutorial Diseño Android: Dashboard UI con LinearLayout. El problema de esta técnica es que estamos limitados a utilizar sólo LinearLayout y que el «anidamiento» de los mismos si se utiliza layout_weight penaliza el rendimiento de la generación de la interfaz gráfica debido a los cálculos realizados para obtener el tamaño a utilizar.
IMPORTANTE: Google abandonó el desarrollo de esta librería en Android 26 y recomienda utilizar en su lugar ConstraintLayout.
En Agosto de 2015 Google publicó en un módulo de la librería de compatibilidad dos nuevos layout que permiten definir las dimensiones de los View que contienen mediante porcentajes : PercentRelativeLayout y PercentFrameLayout. Las «versiones Percent» de estos layout añaden nuevos atributos que permiten definir dimensiones relativas tanto para el propio elemento como para sus márgenes.
Posteriormente Google actualizó esta librería para añadir la posibilidad de definir un aspect ratio.
Para poder utilizar estos layout debemos incluir en nuestro proyecto el módulo de la librería de compatibilidad denominado «percent». En Android Studio basta con añadir en /app/build.gradle
compile 'com.android.support:percent:23.1.1'
Para más información sobre la importación de librerías en Eclipse ADT y Android Studio, consultar este artículo.
Dimensiones relativas
Veamos un ejemplo sencillo: un PercentRelativeLayout que simula dos filas de bloques de distinto color. Cada fila tendrá de altura la mitad del espacio disponible, la primera mostrará dos bloques y la segunda cuatro. Asimismo, y a modo de ejemplo, aplicaremos un margen relativo a ambos lados de la primera fila. El ejemplo también incluye la utilización de la Toolbar. Obsérvese que para estos atributos hay que utilizar el namespace app.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:minHeight="?attr/actionBarSize" app:popupTheme="@style/Theme.AppCompat.Light" app:theme="@style/ThemeOverlay.AppCompat.ActionBar" /> <android.support.percent.PercentRelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!-- ROW 1--> <View android:id="@+id/blue" android:layout_gravity="center_horizontal" android:background="@color/blue" app:layout_heightPercent="@fraction/half" app:layout_widthPercent="@fraction/half_margin" app:layout_marginLeftPercent="@fraction/margin"/> <View android:id="@+id/orange" android:layout_gravity="center_horizontal" android:layout_toRightOf="@id/blue" android:background="@color/orange" app:layout_heightPercent="@fraction/half" app:layout_widthPercent="@fraction/half_margin" app:layout_marginRightPercent="@fraction/margin"/> <!-- ROW 2--> <View android:id="@+id/teal" android:layout_below="@id/blue" android:layout_gravity="center_horizontal" android:background="@color/teal" app:layout_heightPercent="@fraction/half" app:layout_widthPercent="@fraction/quarter" /> <View android:id="@+id/red" android:layout_below="@id/blue" android:layout_gravity="center_horizontal" android:layout_toRightOf="@id/teal" android:background="@color/red" app:layout_heightPercent="@fraction/half" app:layout_widthPercent="@fraction/quarter" /> <View android:id="@+id/brown" android:layout_below="@id/orange" android:layout_gravity="center_horizontal" android:layout_toRightOf="@id/red" android:background="@color/brown" app:layout_heightPercent="@fraction/half" app:layout_widthPercent="@fraction/quarter" /> <View android:id="@+id/bluegray" android:layout_below="@id/orange" android:layout_gravity="center_horizontal" android:layout_toRightOf="@id/brown" android:background="@color/bluegrey" app:layout_heightPercent="@fraction/half" app:layout_widthPercent="@fraction/quarter" /> </android.support.percent.PercentRelativeLayout> </LinearLayout>
Las dimensiones se han definido en el fichero /res/values/dimens.xml.
<?xml version="1.0" encoding="utf-8"?> <resources> <fraction name="half">50%</fraction> <fraction name="margin">2%</fraction> <fraction name="half_margin">48%</fraction> <fraction name="quarter">25%</fraction> </resources>
Aspect ratio
La nueva propiedad layout_aspectRatio amplía las posibilidades del PercentRelativeLayout y permite definir una única dimensión (alto o ancho) de tal modo que a la otra se le aplique la relación de aspecto que queramos cuyo valor, en porcentaje, es el ratio width:height.
Vamos a considerar los dos bloques del ejemplo que se reparten la anchura el 50%. Al primero le asignamos un aspectratio del 100% para que altura y anchura sean iguales, pero al segundo le asignamos un aspectratio del 50% para que la altura sea el doble que la anchura.
<View android:id="@+id/blue" android:layout_gravity="center_horizontal" android:background="@color/blue" app:layout_widthPercent="50%" app:layout_aspectRatio="100%"/> <View android:id="@+id/orange" android:layout_gravity="center_horizontal" android:layout_toRightOf="@id/blue" android:background="@color/orange" app:layout_widthPercent="50%" app:layout_aspectRatio="50%"/>
El proyecto completo para Android Studio se encuentra en Github. Para más información sobre cómo utilizar GitHub, consultar este artículo.