Skip to content

Most visited

Recently visited

navigation

Compatibilidad con diferentes tamaños de pantalla

Esta lección te muestra cómo admitir diferentes tamaños de pantalla con los siguientes pasos:

Cómo utilizar "wrap_content" y "match_parent"

Para asegurarte de que tu diseño sea flexible y que se adapte a diferentes tamaños de pantalla, deberías utilizar "wrap_content" y "match_parent" para el ancho y altura de algunos componentes de vista. Si usas "wrap_content", se fija el ancho o la altura de la vista en el tamaño mínimo necesario para adaptarse al contenido dentro de esa vista, mientras "match_parent" hace que el componente se expanda para adaptarse al tamaño de la vista primaria.

Al utilizar los valores de tamaño "wrap_content" y "match_parent" en lugar de tamaños codificados de forma rígida, tus vistas pueden utilizar solo el espacio requerido para esa vista o bien ampliarse hasta rellenar el espacio disponible, respectivamente. Por ejemplo:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout android:layout_width="match_parent" 
                  android:id="@+id/linearLayout1"  
                  android:gravity="center"
                  android:layout_height="50dp">
        <ImageView android:id="@+id/imageView1" 
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
                   android:src="@drawable/logo"
                   android:paddingRight="30dp"
                   android:layout_gravity="left"
                   android:layout_weight="0" />
        <View android:layout_height="wrap_content" 
              android:id="@+id/view1"
              android:layout_width="wrap_content"
              android:layout_weight="1" />
        <Button android:id="@+id/categorybutton"
                android:background="@drawable/button_bg"
                android:layout_height="match_parent"
                android:layout_weight="0"
                android:layout_width="120dp"
                style="@style/CategoryButtonStyle"/>
    </LinearLayout>

    <fragment android:id="@+id/headlines" 
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="match_parent" />
</LinearLayout>

Observa cómo el ejemplo utiliza "wrap_content" y "match_parent" para el tamaño de los componentes en lugar de dimensiones específicas. Esto permite que el diseño se adapte correctamente a diferentes tamaños y orientaciones de pantalla.

Por ejemplo, así se ve el diseño en modo retrato y en modo de paisaje. Observa que los tamaños de los componentes se adaptan automáticamente a la altura y al ancho:

Figura 1: Ejemplo de app News Reader en el modo vertical (izquierda) y horizontal (derecha).

Cómo utilizar RelativeLayout

Puedes crear diseños medianamente complejos usando instancias anidadas de LinearLayout, y combinaciones de tamaños "wrap_content" y "match_parent". Sin embargo, LinearLayout no te permite controlar con precisión las relaciones espaciales de las vistas secundarias. Las vistas de un LinearLayout simplemente se alinean en paralelo. Si necesitas que las vistas secundarias se orienten de otra forma que no sea en línea recta, a menudo la mejor solución es utilizar un RelativeLayout, que te permite especificar tu diseño según las relaciones espaciales entre los componentes. Por ejemplo, puedes alinear una vista secundaria en el lado izquierdo y otra vista en el lado derecho de la pantalla.

Por ejemplo:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/label"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Type here:"/>
    <EditText
        android:id="@+id/entry"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/label"/>
    <Button
        android:id="@+id/ok"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/entry"
        android:layout_alignParentRight="true"
        android:layout_marginLeft="10dp"
        android:text="OK" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/ok"
        android:layout_alignTop="@id/ok"
        android:text="Cancel" />
</RelativeLayout>

La figura 2 muestra cómo se ve este diseño en una pantalla QVGA.

Figura 2: Captura de pantalla en una pantalla QVGA (pequeña).

La figura 3 muestra cómo se ve este diseño en una pantalla más grande.

Figura 3: Captura de pantalla en una pantalla WSVGA (grande).

Observa que, aunque cambió el tamaño de los componentes, sus relaciones espaciales se mantienen según lo especificado por RelativeLayout.LayoutParams.

Cómo utilizar calificadores de tamaño

Existen límites al utilizar un diseño flexible o un diseño relativo como los de la sección anterior. Mientras que esos diseños se adaptan a diferentes pantallas al estirar el espacio entre los componentes y al rededor de ellos, puede que no ofrezcan la mejor experiencia de usuario para cada tamaño de pantalla. Por lo tanto, tu aplicación no solo debería implementar diseños flexibles, sino que también debería ofrecer varios diseños alternativos para diferentes configuraciones de pantalla. Esto se logra usando calificadores de configuración, lo cual permite que el tiempo de ejecución seleccione automáticamente el recurso adecuado según la configuración actual del dispositivo (por ejemplo, un diseño diferente para diferentes tamaños de pantalla).

Por ejemplo, muchas aplicaciones implementan el patrón de “panel dual” para pantallas grandes (la app podría mostrar una lista de elementos en un panel y el contenido en otro panel). Las pantallas de tablets y TV son lo suficientemente grandes para que ambos paneles aparezcan a la vez; pero las pantallas de teléfonos deben mostrarlos por separado. Por lo tanto, para implementar estos diseños, puedes utilizar los siguientes archivos:

Observa el calificador large en el nombre de directorio del segundo diseño. Este diseño se seleccionará en dispositivos con pantallas clasificadas como grandes (por ejemplo, tablets de 7" y superiores). El otro diseño (sin calificadores) se seleccionará para dispositivos más pequeños.

Cómo utilizar el calificador de ancho mínimo

Una de las dificultades que tenían los desarrolladores con los dispositivos Android anteriores a la versión 3.2 era el contenedor de tamaño de pantalla "grande", que incluye a Dell Streak, Galaxy Tab original y tablets de 7" en general. Sin embargo, es posible que muchas aplicaciones quieran mostrar diferentes diseños para diferentes dispositivos de esta categoría (por ejemplo, para dispositivos de 5” y de 7”), aunque todos estos dispositivos se consideran de pantalla “grande”. Es por eso que Android introdujo el calificador de "ancho mínimo" (entre otros) en Android 3.2.

El calificador de ancho mínimo te permite tener como destino pantallas que tengan un ancho mínimo determinado en dp. Por ejemplo, la típica tablet de 7" tiene un ancho mínimo de 600 dp, por lo que si quieres que tu IU tenga dos paneles en esas pantallas (pero únicamente una lista en pantallas más pequeñas), puedes utilizar los mismos dos diseños de la sección anterior para los diseños de panel único y de panel dual; solo que en lugar de utilizar el calificador de tamaño large, utiliza sw600dp para indicar que el diseño de panel dual se utiliza con las pantallas cuyo ancho mínimo es de 600 dp:

Esto significa que los dispositivos cuyo ancho mínimo sea igual o superior a 600 dp seleccionarán el diseño layout-sw600dp/main.xml (panel dual), mientras que las pantallas más pequeñas seleccionarán el diseño layout/main.xml (panel único).

Sin embargo, esto no funcionará bien en dispositivos anteriores a Android 3.2, ya que no reconocen sw600dp como un calificador de tamaño, por lo que también tendrás que seguir utilizando el calificador large. Por lo tanto, debes contar con un archivo llamado res/layout-large/main.xml idéntico a res/layout-sw600dp/main.xml. En la siguiente sección, verás una técnica que te permite evitar que se dupliquen los archivos de diseños de esta manera.

Cómo utilizar alias de diseño

El calificador de ancho mínimo solo se encuentra disponible en Android 3.2 o superior. Por lo tanto, deberías seguir utilizando los contenedores de tamaño abstracto (pequeño, normal, grande y extragrande) para que sean compatibles con versiones anteriores. Por ejemplo, si quieres que tu IU tenga un diseño de panel único en teléfonos pero multipanel en tablets de 7", TV y otros dispositivos grandes, tendrás que utilizar los siguientes archivos:

Los dos últimos archivos son idénticos, porque uno de ellos se utilizará con dispositivos Android 3.2 y el otro con tablets y TV con versiones anteriores de Android.

Para evitar la duplicación del mismo archivo para tablets y TV (y los dolores de cabeza por el mantenimiento que conlleva), puedes utilizar archivos alias. Por ejemplo, puedes establecer los siguientes diseños:

Y añadir estos dos archivos:

Estos dos últimos archivos tienen el mismo contenido, pero en realidad no definen el diseño. Solo configuran main para que sea un alias de main_twopanes. Debido a que estos archivos tienen selectores large y sw600dp, se aplican a tablets y a TV sin importar la versión de Android (las TV y tablets anteriores a la versión 3.2 usarán large, y las TV y tablets posteriores a la versión 3.2 sw600dp).

Cómo utilizar calificadores de orientación

Algunos diseños funcionan bien tanto en modo horizontal como vertical, pero la mayoría de ellos puede beneficiarse de los ajustes. A continuación, se indica cómo se comporta el diseño según cada tamaño y orientación de la pantalla en el ejemplo de app News Reader:

Cada uno de estos diseños se define en un archivo XML en el directorio res/layout/. Para determinar luego cada diseño según las diferentes configuraciones de pantalla, la app usa alias de diseño para asignarlos a cada configuración:

res/layout/onepane.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="match_parent" />
</LinearLayout>

res/layout/onepane_with_bar.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout android:layout_width="match_parent" 
                  android:id="@+id/linearLayout1"  
                  android:gravity="center"
                  android:layout_height="50dp">
        <ImageView android:id="@+id/imageView1" 
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
                   android:src="@drawable/logo"
                   android:paddingRight="30dp"
                   android:layout_gravity="left"
                   android:layout_weight="0" />
        <View android:layout_height="wrap_content" 
              android:id="@+id/view1"
              android:layout_width="wrap_content"
              android:layout_weight="1" />
        <Button android:id="@+id/categorybutton"
                android:background="@drawable/button_bg"
                android:layout_height="match_parent"
                android:layout_weight="0"
                android:layout_width="120dp"
                style="@style/CategoryButtonStyle"/>
    </LinearLayout>

    <fragment android:id="@+id/headlines" 
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="match_parent" />
</LinearLayout>

res/layout/twopanes.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="400dp"
              android:layout_marginRight="10dp"/>
    <fragment android:id="@+id/article"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.ArticleFragment"
              android:layout_width="fill_parent" />
</LinearLayout>

res/layout/twopanes_narrow.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="200dp"
              android:layout_marginRight="10dp"/>
    <fragment android:id="@+id/article"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.ArticleFragment"
              android:layout_width="fill_parent" />
</LinearLayout>

Una vez definidos todos los diseños posibles, solo se debe asignar el diseño adecuado a cada configuración a través de calificadores de configuración. Ahora ya puedes utilizar la técnica de los alias de diseño:

res/values/layouts.xml:

<resources>
    <item name="main_layout" type="layout">@layout/onepane_with_bar</item>
    <bool name="has_two_panes">false</bool>
</resources>

res/values-sw600dp-land/layouts.xml:

<resources>
    <item name="main_layout" type="layout">@layout/twopanes</item>
    <bool name="has_two_panes">true</bool>
</resources>

res/values-sw600dp-port/layouts.xml:

<resources>
    <item name="main_layout" type="layout">@layout/onepane</item>
    <bool name="has_two_panes">false</bool>
</resources>

res/values-large-land/layouts.xml:

<resources>
    <item name="main_layout" type="layout">@layout/twopanes</item>
    <bool name="has_two_panes">true</bool>
</resources>

res/values-large-port/layouts.xml:

<resources>
    <item name="main_layout" type="layout">@layout/twopanes_narrow</item>
    <bool name="has_two_panes">true</bool>
</resources>

Cómo utilizar mapas de bits de NinePatch

Admitir diferentes tamaños de pantalla normalmente implica que tus recursos de imagen también deben poder adaptarse a distintos tamaños. Por ejemplo, el fondo de un botón debe adaptarse a cualquier forma de botón a la que se aplique.

Si utilizas imágenes comunes en componentes que pueden cambiar de tamaño, observarás rápidamente que los resultados no serán nada impresionantes, ya que el tiempo de ejecución estirará o encogerá las imágenes de manera uniforme. La solución es utilizar mapas de bits de NinePatch, que son archivos PNG con formato especial que indican las áreas que se pueden estirar y las que no.

Por lo tanto, al diseñar mapas de bits que se utilizarán en componentes con tamaño variable, utiliza siempre imágenes de NinePatch. Para convertir un mapa de bits en una imagen de NinePatch, puedes empezar con una imagen común (figura 4, ampliada cuatro veces para mayor claridad).

Figura 4: button.png

A continuación, puedes pasarla por la utilidad draw9patch del SDK (que se encuentra en el directorio tools/), en la que puedes marcar las áreas que se deben estirar dibujando píxeles a lo largo de los bordes izquierdo y superior. También puedes marcar el área que debe incluir el contenido al dibujar píxeles a lo largo de los bordes inferior y derecho, como se muestra en la figura 5.

Figura 5: button.9.png

Observa los píxeles negros situados junto a los bordes. Los que aparecen en los bordes superior e izquierdo indican los lugares en los que se puede estirar la imagen, mientras que los que aparecen en los bordes inferior y derecho indican dónde se debe situar el contenido.

Además, observa la extensión .9.png. Debes usar esta extensión, ya que de esta manera el framework determina que se trata de una imagen de nine-patch, en lugar de una imagen PNG común.

Cuando utilizas este fondo en un componente (definiendo android:background="@drawable/button"), el framework estira la imagen correctamente para adaptar el tamaño del botón, como se muestra en varios tamaños en la figura 6.

Figura 6: Botón en el que se usa la imagen de nine-patch button.9.png en diferentes tamaños.

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Follow Google Developers on WeChat

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)