Cómo brindar compatibilidad con diferentes tamaños de pantalla

Los dispositivos Android vienen de todas formas y tamaños, por lo que el diseño de tu app debe ser flexible. Es decir que, en lugar de definir un diseño con dimensiones rígidas para un tamaño de pantalla y una relación de aspecto determinados, tu diseño debería ajustarse a pantallas de diferentes tamaños y orientaciones.

Al ser compatible con muchas pantallas, una gran cantidad de usuarios con dispositivos diferentes podrá usar tu app, mediante un único APK. Además, al hacer que tu app funcione en distintos tamaños de pantalla, admitirá ajustes en la configuración de la ventana en el dispositivo, como cuando el usuario habilita el modo Multiventana.

En esta página, se muestra cómo hacer que tu app admita diferentes tamaños de pantalla con las siguientes técnicas:

  • Usa dimensiones de vista que permitan cambiar el tamaño del diseño.
  • Crea diseños de IU alternativos en función de la configuración de la pantalla.
  • Proporciona mapas de bits que puedan estirar las vistas.

Sin embargo, debes tener en cuenta que adaptar tu app a diferentes tamaños de pantalla no necesariamente hace que esta sea compatible con todos los factores de forma de Android. Deberás realizar pasos adicionales para agregar compatibilidad con dispositivos Android Wear, Android TV, Android Auto y con el Sistema operativo Chrome.

Si quieres conocer las pautas de diseño a fin de crear IU para diferentes pantallas, consulta los lineamientos sobre el material de IU receptiva.

Cómo crear un diseño flexible

Independientemente del perfil de hardware con el que quieras brindar compatibilidad primero, debes crear un diseño que sea receptivo incluso para las variaciones más leves de tamaño de pantalla.

Cómo usar ConstraintLayout

La mejor manera de crear un diseño receptivo para diferentes tamaños de pantalla es usar ConstraintLayout como diseño de base de tu IU. ConstraintLayout te permite especificar la posición y el tamaño de cada vista en función de las relaciones espaciales con otras vistas del diseño. De esta manera, todas las vistas pueden moverse y estirarse a la vez, a medida que cambia el tamaño de la pantalla.

La forma más fácil de crear un diseño con ConstraintLayout es usar el editor de diseño de Android Studio. Este te permite arrastrar nuevas vistas al diseño, asociar sus restricciones a la vista superior y a otras vistas secundarias, y editar las propiedades de la vista sin la necesidad de editar ningún archivo XML manualmente (ver figura 1).

Para obtener más información, consulta Cómo crear una IU receptiva con ConstraintLayout.

Figura 1: Se muestra un archivo ConstraintLayout en el editor de diseño de Android Studio

Sin embargo, ConstraintLayout no solucionará todos los problemas con el diseño (en especial para las listas cargadas de forma dinámica, en cuyo caso debes usar RecyclerView). Independientemente del diseño que utilices, deberías evitar los tamaños de diseños hard-coded (consulta la siguiente sección).

Cómo evitar usar tamaños de diseño hard-coded

Si quieres asegurarte de que tu diseño sea flexible y se adapte a diferentes tamaños de pantalla, debes usar "wrap_content" y "match_parent" para la altura y el ancho de la mayoría de los componentes de la vista, en lugar de usar tamaños hard-coded.

"wrap_content" le indica a la vista que debe establecer el tamaño que sea necesario para adaptarse al contenido de esa vista.

"match_parent" hace que la vista se expanda tanto como sea posible dentro de la vista superior.

Por ejemplo:

<TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/lorem_ipsum" />
    

Si bien el diseño real de esta vista depende de otros atributos en la vista superior y cualquier vista del mismo nivel, este atributo TextView intenta establecer su ancho para que rellene todo el espacio disponible (match_parent) y establecer su altura a la medida exacta que requiere la longitud de texto (wrap_content). De esta manera, la vista se adapta a diferentes tamaños de pantalla y a diferentes longitudes de texto.

En la figura 2, se muestra cómo el ancho de la vista de texto que usa "match_parent" se ajusta a medida que el ancho de la pantalla cambia con la orientación del dispositivo.

Figura 2: Vista de texto flexible

Si usas un LinearLayout, también puedes expandir las vistas secundarias con el volumen del diseño, de manera que cada vista ocupe el espacio restante proporcional a su valor de volumen. Sin embargo, el uso de volúmenes en un LinearLayout anidado requiere que el sistema realice varias pasadas de diseño para determinar el tamaño de cada vista, lo que ralentiza el rendimiento de tu IU. Por suerte, ConstraintLayout puede generar casi todos los diseños posibles con LinearLayout sin afectar el rendimiento, por lo que deberías intentar convertir tu diseño a ConstraintLayout. Luego, puedes definir los diseños con volumen mediante cadenas de restricciones.

Cómo crear diseños alternativos

Si bien el diseño siempre debe responder a diferentes tamaños de pantalla estirando el espacio entre las vistas y alrededor de estas, es posible que no brinde la mejor experiencia del usuario para todos los tamaños de pantalla. Por ejemplo, la IU que diseñaste para un teléfono probablemente no brinde una buena experiencia en una tablet. Por lo tanto, también debes proporcionar recursos de diseño alternativos a fin de optimizar el diseño de la IU para determinados tamaños de pantalla.

Figura 3: La misma app en pantallas de distintos tamaños usa un diseño diferente para cada una

Puedes proporcionar diseños específicos de cada pantalla creando directorios res/layout/ adicionales (uno para cada configuración de pantalla que requiera un diseño diferente) y, luego, agregar un calificador de configuración de pantalla al nombre del directorio layout (por ejemplo layout-w600dp para pantallas que tengan 600 dp de ancho disponible).

Estos calificadores de configuración representan el espacio de pantalla visible disponible para la IU de tu app. El sistema considera cualquier decoración (como la barra de navegación) y cambio en la configuración de la ventana (como cuando el usuario habilita el modo Multiventana) cuando selecciona el diseño de tu app.

Para crear un diseño alternativo en Android Studio (con la versión 3.0 o posterior) haz lo siguiente:

  1. Abre tu diseño predeterminado y, luego, haz clic en Orientation for Preview  en la barra de herramientas.
  2. En la lista desplegable, selecciona una opción para crear una variante recomendada, como Create Landscape Variant, o bien haz clic en Create Other.
  3. Si eliges Create Other, aparecerá la opción Select Resource Directory. Aquí deberás seleccionar un calificador de pantalla del lado izquierdo y agregarlo a la lista de Calificadores elegidos. Cuando termines de agregar calificadores, haz clic en Aceptar. (Consulta las siguientes secciones para obtener información sobre los calificadores de tamaños de pantalla).

De esta manera, se crea un archivo de diseño duplicado en el directorio de diseño correspondiente para que puedas empezar a personalizar el diseño de esa variante de pantalla.

Cómo usar el calificador de ancho mínimo

El calificador de tamaño de pantalla "ancho mínimo" te permite proporcionar diseños alternativos para pantallas que tienen un ancho mínimo medido en píxeles independientes de la densidad (dp o dip).

Al describir el tamaño de la pantalla como una medida de píxeles independientes de la densidad, Android te permite crear diseños para dimensiones de pantalla muy específicas y evitar cualquier preocupación que tengas respecto de las diferentes densidades de píxeles.

Por ejemplo, puedes generar un diseño llamado main_activity que esté optimizado para teléfonos celulares y tablets si creas diferentes versiones del archivo en directorios de la siguiente manera:

    res/layout/main_activity.xml           # For handsets (smaller than 600dp available width)
    res/layout-sw600dp/main_activity.xml   # For 7” tablets (600dp wide and bigger)
    

El calificador de ancho mínimo especifica el lado más pequeño de la pantalla, independientemente de la orientación actual del dispositivo, por lo que es una manera sencilla de especificar el tamaño de pantalla total disponible para tu diseño.

A continuación, se muestra cómo los valores de ancho mínimo se corresponden con los tamaños de pantalla típicos:

  • 320 dp: una pantalla típica de teléfono (240 x 320 ldpi, 320 x 480 mdpi, 480 x 800 hdpi, etc.)
  • 480 dp: una pantalla de teléfono grande de ~5" (480 x 800 mdpi)
  • 600 dp: una tablet de 7" (600 x 1024 mdpi)
  • 720 dp: una tablet de 10" (720 x 1280 mdpi, 800 x 1280 mdpi, etc.)

En la figura 4, se proporciona una vista más detallada de cómo los diferentes anchos de dp de pantalla generalmente se corresponden con los tamaños y las orientaciones de pantalla diferentes.

Figura 4: Interrupciones de ancho recomendadas para admitir diferentes tamaños de pantalla

Recuerda que todas las cifras del calificador de ancho mínimo corresponden a píxeles independientes de la densidad, porque lo que importa es la cantidad de espacio de pantalla disponible luego de que el sistema calcula la densidad de píxeles (no la resolución de píxeles bruta).

Cómo usar el calificador de ancho disponible

En lugar de cambiar el diseño en función del ancho mínimo de la pantalla, puedes cambiar tu diseño según el ancho o la altura disponible actualmente. Por ejemplo, si tienes un diseño de dos paneles, puede que quieras usarlo cada vez que la pantalla proporcione un ancho mínimo de 600 dp, lo que podría variar en función de si el dispositivo se encuentra en orientación horizontal o vertical. En este caso, deberías usar el calificador de "ancho disponible" de la siguiente manera:

    res/layout/main_activity.xml         # For handsets (smaller than 600dp available width)
    res/layout-w600dp/main_activity.xml  # For 7” tablets or any screen with 600dp
                                         #   available width (possibly landscape handsets)
    

Si te preocupa la altura disponible, puedes hacer lo mismo con el calificador de "altura disponible". Por ejemplo, layout-h600dp para pantallas con al menos 600 dp de altura de pantalla.

Cómo agregar calificadores de orientación

Aunque puedes admitir todas las variaciones de tamaño con solo usar combinaciones de calificadores de "ancho mínimo" y "ancho disponible", es posible que también quieras cambiar la experiencia del usuario cuando este alterne entre las orientaciones vertical y horizontal.

Para ello, puedes agregar los calificadores port y land a los nombres de tus directorios de recursos. Asegúrate de que se ubiquen después de los otros calificadores de tamaño. Por ejemplo:

    res/layout/main_activity.xml                # For handsets
    res/layout-land/main_activity.xml           # For handsets in landscape
    res/layout-sw600dp/main_activity.xml        # For 7” tablets
    res/layout-sw600dp-land/main_activity.xml   # For 7” tablets in landscape
    

Para obtener más información sobre todos los calificadores de configuración de pantalla, consulta la tabla 2 en la guía sobre Cómo proporcionar recursos.

Cómo modularizar componentes de la IU con fragmentos

Cuando diseñes tu app para varios tamaños de pantalla, asegúrate de no duplicar innecesariamente el comportamiento de tu IU en las actividades. Para ello, debes usar fragmentos a fin de extraer la lógica de tu IU en componentes individuales. Luego, podrás combinar los fragmentos para crear diseños de varios paneles cuando ejecutes la app en una pantalla grande o ubicarlos en actividades individuales cuando ejecutes la app en un teléfono celular.

Por ejemplo, una app de noticias en una tablet podría mostrar una lista de artículos en el lado izquierdo y un artículo completo en el lado derecho (al seleccionar un artículo del lado izquierdo, se actualiza la vista del artículo en el lado derecho). Sin embargo, en un teléfono celular, estos dos componentes deben aparecer en pantallas separadas (al seleccionar un artículo de la lista, se cambia toda la pantalla para mostrarlo).

Para obtener más información, consulta Cómo crear una IU dinámica con fragmentos.

Compatibilidad con Android 3.1 con calificadores de tamaño heredados

Si tu app admite Android 3.1 (nivel de API 12) o versiones anteriores, deberás usar los calificadores de tamaño heredados además de los calificadores de ancho mínimo/disponible descriptos anteriormente.

En el ejemplo anterior, si quieres un diseño de dos paneles en dispositivos más grandes, debes usar el calificador de configuración "grande" para que admita la versión 3.1 y versiones anteriores. Por lo tanto, para implementar estos diseños en esas versiones anteriores, es posible que necesites los siguientes archivos:

    res/layout/main_activity.xml           # For handsets (smaller than 640dp x 480dp)
    res/layout-large/main_activity.xml     # For small tablets (640dp x 480dp and bigger)
    res/layout-xlarge/main_activity.xml    # For large tablets (960dp x 720dp and bigger)
    

Cómo usar alias de diseño

Para admitir versiones anteriores y posteriores a Android 3.2, tendrás que usar los calificadores grandes y de ancho mínimo para tus diseños. Por lo tanto, tendrías un archivo llamado res/layout-large/main.xml que podría ser idéntico a res/layout-sw600dp/main.xml.

Para evitar la duplicación del mismo archivo, puedes usar archivos de alias. Por ejemplo, puedes definir los siguientes diseños:

    res/layout/main.xml            # single-pane layout
    res/layout/main_twopanes.xml   # two-pane layout
    

Y agregar estos dos archivos:

  • res/values-large/layout.xml:
        <resources>
            <item name="main" type="layout">@layout/main_twopanes</item>
        </resources>
        
  • res/values-sw600dp/layout.xml:
        <resources>
            <item name="main" type="layout">@layout/main_twopanes</item>
        </resources>
        

Estos dos archivos tienen el mismo contenido, pero en realidad no definen el diseño. Solo configuran main para que sea un alias de main_twopanes. Como estos archivos tienen los selectores large y sw600dp, se aplican a pantallas grandes, independientemente de la versión de Android que ejecuten (las tablets y TV con versiones anteriores a la 3.2 coinciden con large y las posteriores coincidirán con sw600dp).

Cómo crear mapas de bits de 9-Patch estirables

Si usas un mapa de bits como fondo en una vista que cambia de tamaño, verás que Android escalará tu imagen a medida que la vista se expanda o se contraiga en función del tamaño de la pantalla o del contenido en la vista, lo que suele provocar imágenes borrosas o algún otro artefacto de escalamiento. La solución es utilizar mapas de bits de 9-Patch, que son archivos PNG con formato especial que indican las áreas que se pueden estirar y las que no.

Un mapa de bits de 9-Patch es básicamente un archivo PNG estándar, pero con un borde de 1 píxel adicional que indica que los píxeles deben estirarse (y con una extensión .9.png en lugar de .png. Como se muestra en la figura 5, la intersección entre las líneas negras del lado izquierdo y el borde superior es el área del mapa de bits que puede estirarse.

También puedes definir una región segura en la que el contenido se ubique dentro de la vista si agregas, de manera similar, líneas en el lado derecho y en el borde inferior.

Figura 5: Imagen de un 9-Patch (button.9.png)

Cuando aplicas un 9-Patch como fondo de una vista, el marco de trabajo estira la imagen correctamente para ajustar el tamaño del botón.

Para obtener información sobre cómo crear una imagen de 9-Patch a partir de un mapa de bits, consulta Cómo crear mapas de bits de tamaño ajustable.

Cómo probar tu app en todos los tamaños de pantalla

Es importante que pruebes tu app en varios tamaños de pantalla para asegurarte de que la IU se escale correctamente. Si no tienes acceso a dispositivos físicos de todos los tamaños de pantalla, puedes usar el emulador de Android para emular cualquier tamaño de pantalla.

Si prefieres probarla en dispositivos físicos, pero no quieres comprarlos, puedes usar el Test Lab de Firebase para acceder a dispositivos en el centro de datos de Google.

Cómo declarar la compatibilidad con tamaños de pantalla específicos

Si no quieres que se ejecute tu app en determinados tamaños de pantalla, puedes establecer límites que especifiquen cuánto puede cambiarse el tamaño de la pantalla o incluso restringir los dispositivos que pueden instalar tu app en función de la configuración de su pantalla. Para obtener más información, consulta Cómo declarar una compatibilidad de pantalla restringida.