Los desarrolladores suelen encontrar dificultades únicas cuando crean aplicaciones para dispositivos plegables, en especial, para dispositivos como el Samsung Trifold o el Pixel Fold original, que se abre en formato horizontal (rotation_0 = landscape). Entre los errores de los desarrolladores, se incluyen los siguientes:
- Suposiciones incorrectas sobre la orientación del dispositivo
- Casos de uso que se pasan por alto
- No se pueden volver a calcular ni almacenar en caché los valores en los cambios de configuración.
Entre los problemas específicos relacionados con el dispositivo, se incluyen los siguientes:
- Una discrepancia en la orientación natural del dispositivo entre las pantallas interior y exterior (suposiciones basadas en rotation_0 = vertical), lo que provoca que las apps fallen en los recorridos de plegado y desplegado
- Diferentes densidades de pantalla y control incorrecto del cambio de configuración de densidad
- Problemas de vista previa de la cámara causados por la dependencia del sensor de la cámara en la orientación natural
Para ofrecer una experiencia del usuario de alta calidad en dispositivos plegables, enfócate en las siguientes áreas críticas:
- Determina la orientación de la app según el área de pantalla real que ocupa, no la orientación física del dispositivo.
- Actualiza las vistas previas de la cámara para administrar correctamente la orientación del dispositivo y las relaciones de aspecto, evitar las vistas previas laterales y prevenir las imágenes estiradas o recortadas.
- Mantén la continuidad de la app durante el plegado o desplegado del dispositivo. Para ello, retén el estado con
ViewModelo enfoques similares, o bien controla de forma manual los cambios de densidad de pantalla y los cambios de orientación, lo que evita que se reinicie la app o se pierda el estado. - En el caso de las apps que utilizan sensores de movimiento, ajusta el sistema de coordenadas para que se alinee con la orientación actual de la pantalla y evita suposiciones basadas en rotation_0 = retrato, lo que garantiza interacciones precisas del usuario.
Compilación adaptable
Si tu app ya es adaptable y cumple con el nivel optimizado (nivel 2) que se describe en los lineamientos de calidad de las apps para pantallas grandes, debería funcionar bien en dispositivos plegables. De lo contrario, antes de verificar los detalles específicos de los dispositivos plegables de tríptico y horizontales, revisa los siguientes conceptos básicos del desarrollo adaptable para Android.
Diseños adaptables
Tu IU debe controlar no solo los diferentes tamaños de pantalla, sino también los cambios en tiempo real en la relación de aspecto, como el despliegue y el ingreso a los modos de ventanas múltiples o de ventanas de escritorio. Consulta Acerca de los diseños adaptables para obtener más orientación sobre cómo hacer lo siguiente:
- Diseña e implementa diseños adaptables
- Ajusta la navegación principal de tu app según el tamaño de la ventana
- Usa clases de tamaño de ventana para adaptar la IU de tu app
- Simplifica la implementación de diseños canónicos, como el de lista y detalles, con las APIs de Jetpack.
Clases de tamaño de ventana
Los dispositivos plegables, incluidos los plegables horizontales y los plegables triples, pueden cambiar entre las clases de tamaño de ventana compacta, mediana y expandida de forma instantánea. Comprender e implementar estas clases garantiza que tu app muestre los componentes de navegación y la densidad de contenido correctos para el estado actual del dispositivo.
En el siguiente ejemplo, se usa la biblioteca adaptable de Material 3 para determinar cuánto espacio tiene disponible la app. Para ello, primero se invoca la función currentWindowAdaptiveInfo() y, luego, se usan los diseños correspondientes para las tres clases de tamaño de ventana:
val adaptiveInfo = currentWindowAdaptiveInfo(supportLargeAndXLargeWidth = true)
val windowSizeClass = adaptiveInfo.windowSizeClass
when {
windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_EXPANDED_LOWER_BOUND) -> // Large
windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_MEDIUM_LOWER_BOUND) -> // Medium
else -> // Compact
}
Para obtener más información, consulta Usa clases de tamaño de ventana.
Calidad de las apps para pantallas grandes
Si cumples con los requisitos del nivel 2 (optimización para pantallas grandes) o el nivel 1 (diferenciación para pantallas grandes) de los lineamientos de calidad de las apps para pantallas grandes, te asegurarás de que tu app brinde una experiencia del usuario atractiva en dispositivos plegables con tres pliegues, plegables horizontales y otros dispositivos con pantallas grandes. Los lineamientos abarcan verificaciones críticas en varios niveles para pasar de estar listo para la adaptación a una experiencia diferenciada.
Android 16 y versiones posteriores
En el caso de las apps que se segmentan para Android 16 (nivel de API 36) y versiones posteriores, el sistema ignora las restricciones de orientación, cambio de tamaño y relación de aspecto en pantallas con un ancho más pequeño >= 600 dp. Las apps ocupan toda la ventana de visualización, independientemente de la relación de aspecto o la orientación preferida del usuario, y ya no se usa el modo de compatibilidad de formato letterbox.
Consideraciones especiales
Los teléfonos plegables horizontales y los trípticos presentan comportamientos de hardware únicos que requieren un manejo específico, en particular en lo que respecta a los sensores, la vista previa de la cámara y la continuidad de la configuración (conservación del estado al plegar, desplegar o cambiar el tamaño).
Vista previa de cámara
Un problema común en los dispositivos plegables horizontales o en los cálculos de la relación de aspecto (en situaciones como multiventana, ventanas de escritorio o pantallas conectadas) es cuando la vista previa de la cámara aparece estirada, de lado, recortada o rotada.
Suposiciones no coincidentes
Este problema suele ocurrir en dispositivos plegables y de pantalla grande porque las apps pueden suponer relaciones fijas entre las funciones de la cámara (como la relación de aspecto y la orientación del sensor) y las funciones del dispositivo (como la orientación del dispositivo y la orientación natural).
Los nuevos factores de forma desafían esta suposición. Un dispositivo plegable puede cambiar el tamaño y la relación de aspecto de la pantalla sin que cambie la rotación del dispositivo. Por ejemplo, desplegar un dispositivo cambia la relación de aspecto, pero si el usuario no lo rota, su rotación sigue siendo la misma. Si una app supone que la relación de aspecto se correlaciona con la rotación del dispositivo, es posible que rote o ajuste incorrectamente la vista previa de la cámara. Lo mismo puede ocurrir si una app supone que la orientación del sensor de la cámara coincide con la orientación vertical del dispositivo, lo que no siempre es cierto para los dispositivos plegables horizontales.
Solución 1: Jetpack CameraX (la mejor)
La solución más sencilla y sólida es usar la biblioteca de CameraX de Jetpack. Su elemento de IU PreviewView está diseñado para controlar automáticamente todas las complejidades de la vista previa:
PreviewViewse ajusta correctamente a la orientación del sensor, la rotación del dispositivo y el ajuste de escala.- Mantiene la relación de aspecto de la imagen de la cámara, por lo general, centrándola y recortándola (FILL_CENTER).
- Puedes establecer el tipo de escala en
FIT_CENTERpara agregar barras negras a la vista previa si es necesario.
Para obtener más información, consulta Implementa una vista previa en la documentación de CameraX.
Solución 2: CameraViewfinder
Si usas una base de código de Camera2 existente, la biblioteca CameraViewfinder (retrocompatible con el nivel de API 21) es otra solución moderna. Simplifica la visualización de la transmisión de la cámara usando un TextureView o SurfaceView y aplicando todas las transformaciones necesarias (relación de aspecto, escala y rotación) por ti.
Para obtener más información, consulta la entrada de blog Presentación del visor de la cámara y la guía para desarrolladores Vista previa de la cámara.
Solución 3: Implementación manual de Camera2
Si no puedes usar CameraX o CameraViewfinder, debes calcular manualmente la orientación y la relación de aspecto, y asegurarte de que los cálculos se actualicen con cada cambio de configuración:
- Obtén la orientación del sensor de la cámara (por ejemplo, 0, 90, 180 o 270 grados) de
CameraCharacteristics. - Obtiene la rotación de pantalla actual del dispositivo (por ejemplo, 0, 90, 180 o 270 grados).
- Usa estos dos valores para determinar las transformaciones necesarias para tu
SurfaceViewoTextureView. - Asegúrate de que la relación de aspecto de la salida
Surfacecoincida con la de la vista previa de la cámara para evitar distorsiones. - Es posible que la app de la cámara se ejecute en una parte de la pantalla, ya sea en el modo de ventanas múltiples o de escritorio, o en una pantalla conectada. Por este motivo, no se debe usar el tamaño de la pantalla para determinar las dimensiones del visor de la cámara. En su lugar, usa las métricas de ventana.
Para obtener más información, consulta la guía para desarrolladores de Vista previa de la cámara y el video Tu app de Cámara en diferentes factores de forma.
Solución 4: Realiza acciones básicas de la cámara con un intent
Si no necesitas muchas funciones de la cámara, una solución simple y directa es realizar acciones básicas de la cámara, como capturar una foto o un video, con la aplicación de cámara predeterminada del dispositivo. No necesitas integrar una biblioteca de cámara. En su lugar, usa un Intent.
Para obtener más información, consulta Intenciones de la cámara.
Configuración y continuidad
Los dispositivos plegables mejoran la versatilidad de la IU, pero pueden iniciar más cambios de configuración que los no plegables. Tu app debe administrar estos cambios de configuración y sus combinaciones, como la rotación del dispositivo, el plegado o desplegado, y el cambio de tamaño de la ventana en los modos multiventana o de escritorio, mientras retiene o restablece el estado de la app. Por ejemplo, las apps deben mantener la siguiente continuidad:
- Estado de la app sin fallas ni cambios disruptivos para los usuarios (por ejemplo, cuando se cambian las pantallas o se envía la app a segundo plano)
- Posición de desplazamiento de los campos desplazables
- Texto escrito en los campos de texto y estado del teclado
- Posición de reproducción de contenido multimedia para que la reproducción se reanude en el lugar donde quedó cuando se inició el cambio de configuración
Los cambios de configuración que se activan con frecuencia incluyen screenSize, smallestScreenSize, screenLayout, orientation, density, fontScale, touchscreen y keyboard.
Consulta android:configChanges y Cómo administrar los cambios en la configuración. Para obtener más información sobre cómo administrar el estado de la app, consulta Cómo guardar estados de la IU.
Cambios en la configuración de densidad
Las pantallas interior y exterior de los dispositivos plegables horizontales y de tres pliegues pueden tener diferentes densidades de píxeles. Por lo tanto, administrar el cambio de configuración para density requiere atención adicional. Por lo general, Android reinicia la actividad cuando cambia la densidad de pantalla, lo que puede provocar la pérdida de datos. Para evitar que el sistema reinicie la actividad, declara el control de densidad en tu manifiesto y administra el cambio de configuración de forma programática en tu app.
Configuración de AndroidManifest.xml
density: Declara que la app controlará el cambio de densidad de pantalla.- Otros cambios de configuración: También es bueno declarar otros cambios de configuración que ocurren con frecuencia, por ejemplo,
screenSize,orientation,keyboardHidden,fontScale, etcétera.
Declarar la densidad (y otros cambios de configuración) evita que el sistema reinicie la actividad y, en su lugar, llama a onConfigurationChanged().
Implementación de onConfigurationChanged()
Cuando se produce un cambio de densidad, debes actualizar tus recursos (como volver a cargar mapas de bits o volver a calcular los tamaños de diseño) en la devolución de llamada:
- Verifica que el DPI haya cambiado a
newConfig.densityDpi. - Restablece las vistas personalizadas, los elementos de diseño personalizados, etcétera, a la nueva densidad.
Elementos de recursos para procesar
- Recurso de imagen: Reemplaza mapas de bits y elementos de diseño con recursos específicos de densidad, o bien ajusta la escala directamente.
- Unidad de diseño (conversión de dp a px): Vuelve a calcular el tamaño, el margen y el padding de la vista.
- Tamaño de fuente y texto: Vuelve a aplicar el tamaño de texto de la unidad sp
- Dibujo personalizado de
View/Canvas: Actualiza los valores basados en píxeles que se usan para dibujarCanvas.
Cómo determinar la orientación de la app
Nunca confíes en la rotación física del dispositivo cuando compiles apps adaptativas, ya que se ignorará en dispositivos de pantalla grande y una app en modo multiventana podría tener una orientación diferente a la del dispositivo. En su lugar, usa Configuration.orientation o WindowMetrics para identificar si tu app se encuentra actualmente en orientación horizontal o vertical según el tamaño de la ventana.
Solución 1: Usa Configuration.orientation
Esta propiedad identifica la orientación en la que se muestra actualmente tu app.
Solución 2: Usa WindowMetrics#getBounds()
Puedes obtener los límites de visualización actuales de la app y verificar su ancho y alto para determinar la orientación.
Si necesitas limitar la orientación de las apps en teléfonos (o en las pantallas exteriores de los dispositivos plegables), pero no en dispositivos con pantalla grande, consulta Cómo restringir la orientación de las apps en teléfonos.
Posturas y modos de visualización
Las posiciones y los estados plegables, como el de mesa y el de HALF_OPENED, son compatibles con los dispositivos plegables verticales y horizontales. Sin embargo, los trípticos no admiten la posición de mesa y no se pueden usar HALF_OPENED. En cambio, los teléfonos plegables ofrecen una pantalla más grande para brindar una experiencia del usuario única cuando están completamente desplegados.
Para diferenciar tu app en dispositivos plegables que admiten HALF_OPENED, usa las APIs de WindowManager de Jetpack, como FoldingFeature.
Obtén más información sobre las posturas, los estados y la compatibilidad con la vista previa de la cámara en las siguientes guías para desarrolladores:
- Más información sobre dispositivos plegables
- Cómo hacer que tu app funcione en dispositivos plegables
Los dispositivos plegables ofrecen experiencias de visualización únicas. El modo de pantalla posterior y el modo Dual Screen te permiten crear funciones de pantalla especiales para dispositivos plegables, como una vista previa de Selfie con cámara posterior y pantallas simultáneas pero diferentes en pantallas internas y externas. Para obtener más información, consulta los siguientes recursos:
Cómo bloquear la orientación en la orientación natural del sensor
Para casos de uso muy específicos, en particular, apps que necesitan ocupar toda la pantalla sin relación con el estado plegado del dispositivo, la marca nosensor te permite bloquear la app en la orientación natural del dispositivo. Por ejemplo, en un Pixel Fold, la orientación natural del dispositivo cuando está plegado es vertical, mientras que la orientación natural cuando está desplegado es horizontal. Agregar la marca nosensor obliga a la app a bloquearse en orientación vertical cuando se ejecuta en la pantalla exterior y a bloquearse en horizontal cuando se ejecuta en la pantalla interior.
<activity
android:name=".MainActivity"
android:screenOrientation="nosensor">
Remapeo de sensores de juegos y RE
En el caso de los juegos y las apps de RE, los datos sin procesar de los sensores (como el giroscopio o el acelerómetro) se proporcionan en el sistema de coordenadas fijo del dispositivo. Si el usuario rota el dispositivo para jugar en horizontal, los ejes del sensor no rotan con la pantalla, lo que genera controles incorrectos en el juego.
Para solucionar este problema, verifica el Display.getRotation() actual y reasigna los ejes según corresponda:
- Rotación 0: x=x, y=y
- Rotación de 90°: x=-y, y=x
- Rotación de 180°: x=-x, y=-y
- Rotación de 270°: x=y, y=-x
Para los vectores de rotación (que se usan en apps de brújula o de XR), usa SensorManager.remapCoordinateSystem() para asignar la dirección del lente de la cámara o la parte superior de la pantalla a los nuevos ejes según la rotación actual.
Compatibilidad con apps
Las aplicaciones deben seguir los lineamientos de calidad de las apps para garantizar la compatibilidad en todos los factores de forma y pantallas conectadas. Si una aplicación no puede cumplir con los lineamientos, los fabricantes de dispositivos pueden implementar tratamientos de compatibilidad, aunque esto puede degradar la experiencia del usuario.
Para obtener información adicional, revisa la lista completa de soluciones alternativas de compatibilidad que se proporcionan en la plataforma, en especial las relacionadas con la vista previa de la cámara, las invalidaciones y los cambios en la API de Android 16 que podrían cambiar el comportamiento de tu app.
Para obtener más información sobre cómo compilar apps adaptables, consulta Calidad de las apps para pantallas grandes.