Compatibilité avec les appareils pliables à trois volets et au format paysage

Un appareil pliable au format paysage en position fermée et entièrement ouverte à côté d'un appareil à trois volets en position fermée et entièrement ouverte.

Les développeurs rencontrent souvent des difficultés uniques lorsqu'ils créent des applications pour les appareils pliables, en particulier ceux comme le Samsung Trifold ou le Pixel Fold d'origine, qui s'ouvrent au format paysage (rotation_0 = paysage). Voici quelques exemples d'erreurs commises par les développeurs :

  • Hypothèses incorrectes sur l'orientation de l'appareil
  • Cas d'utilisation négligés
  • Échec du recalcul ou de la mise en cache des valeurs lors des modifications de configuration

Voici quelques exemples de problèmes spécifiques liés aux appareils :

  • Une incohérence dans l'orientation naturelle de l'appareil entre les écrans extérieur et intérieur (hypothèses basées sur rotation_0 = portrait), entraînant l'échec des applications lors des parcours de pliage et de dépliage
  • Gestion incorrecte des différentes densités d'écran et des modifications de configuration de la densité
  • Problèmes d'aperçu de la caméra causés par la dépendance du capteur de la caméra à l'orientation naturelle

Pour offrir une expérience utilisateur de haute qualité sur les appareils pliables, concentrez-vous sur les domaines critiques suivants :

  • Déterminez l'orientation de l'application en fonction de la zone d'écran réelle qu'elle occupe, et non de l'orientation physique de l'appareil.
  • Mettre à jour les aperçus de l'appareil photo pour gérer correctement l'orientation de l'appareil et les formats, éviter les aperçus latéraux et empêcher les images étirées ou recadrées
  • Maintenez la continuité de l'application lorsque l'appareil est plié ou déplié en conservant l'état avec ViewModel ou des approches similaires, ou en gérant manuellement les changements de densité d'écran et d'orientation, ce qui évite les redémarrages de l'application ou la perte d'état.
  • Pour les applications qui utilisent des capteurs de mouvement, ajustez le système de coordonnées pour l'aligner sur l'orientation actuelle de l'écran et évitez les hypothèses basées sur rotation_0 = portrait, ce qui garantit des interactions utilisateur précises.

Créer des applications adaptatives

Si votre application est déjà adaptative et respecte le niveau optimisé (niveau 2) décrit dans les consignes relatives à la qualité des applis sur les grands écrans, elle devrait bien fonctionner sur les appareils pliables. Sinon, avant de vérifier les détails spécifiques des pliables à trois volets et à format paysage, passez en revue les concepts fondamentaux de développement adaptatif Android suivants.

Mises en page adaptatives

Votre UI doit gérer non seulement les différentes tailles d'écran, mais aussi les changements de format en temps réel, comme le déploiement et le passage aux modes multifenêtre ou fenêtré sur ordinateur. Pour savoir comment :

  • Concevoir et implémenter des mises en page adaptatives
  • Ajuster la navigation principale de votre application en fonction de la taille de la fenêtre
  • Utiliser des classes de taille de fenêtre pour adapter l'UI de votre application
  • Simplifiez l'implémentation de mises en page canoniques, telles que la mise en page Liste/Détail, à l'aide des API Jetpack.
Application letterboxée sur un appareil pliable ouvert, et la même application en plein écran avec une mise en page adaptative sur un autre appareil pliable ouvert.
Figure 1. Différence entre les mises en page non adaptatives (letterbox) et adaptatives.

Classes de taille de fenêtre

Les appareils pliables, y compris les pliables à l'horizontale et les pliables à trois volets, peuvent passer instantanément des classes de taille de fenêtre compacte, moyenne et agrandie. Comprendre et implémenter ces classes permet de s'assurer que votre application affiche les composants de navigation et la densité de contenu appropriés pour l'état actuel de l'appareil.

Représentation d'une application sur des appareils de taille compacte, moyenne et agrandie.
Figure 2. Classes de taille de fenêtre.

L'exemple suivant utilise la bibliothèque adaptative Material 3 pour déterminer l'espace disponible dans l'application en appelant d'abord la fonction currentWindowAdaptiveInfo(), puis en utilisant les mises en page correspondantes pour les trois classes de taille de fenêtre :

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
}

Pour en savoir plus, consultez Utiliser des classes de taille de fenêtre.

Critères de qualité des applications sur grand écran

En respectant le niveau 2 (optimisé pour les grands écrans) ou le niveau 1 (différencié pour les grands écrans) des consignes relatives à la qualité des applications sur grand écran, vous vous assurez que votre application offre une expérience utilisateur attrayante sur les appareils à trois volets, les appareils pliables en mode paysage et les autres appareils à grand écran. Elles couvrent des vérifications critiques à plusieurs niveaux pour passer d'une expérience adaptative à une expérience différenciée.

Android 16 ou version ultérieure

Pour les applications ciblant Android 16 (niveau d'API 36) et versions ultérieures, le système ignore les restrictions d'orientation, de redimensionnement et de format sur les écrans dont la plus petite largeur est supérieure ou égale à 600 dp. Les applications remplissent toute la fenêtre d'affichage, quels que soient le format ou l'orientation préférés de l'utilisateur, et le mode de compatibilité letterbox n'est plus utilisé.

Considérations particulières

Les appareils pliables à trois volets et à l'horizontale présentent des comportements matériels uniques qui nécessitent une gestion spécifique, en particulier en ce qui concerne les capteurs, l'aperçu de la caméra et la continuité de la configuration (conservation de l'état lors du pliage, du dépliage ou du redimensionnement).

Aperçu de l'appareil photo

Un problème courant sur les appareils pliables en mode paysage ou lors des calculs de format (dans des scénarios tels que le multifenêtre, le fenêtrage de bureau ou les écrans connectés) se produit lorsque l'aperçu de l'appareil photo apparaît étiré, de côté, recadré ou pivoté.

Hypothèses non concordantes

Ce problème se produit souvent sur les appareils à grand écran et pliables, car les applications peuvent supposer des relations fixes entre les fonctionnalités de l'appareil photo (comme le format et l'orientation du capteur) et les fonctionnalités de l'appareil (comme l'orientation de l'appareil et l'orientation naturelle).

De nouveaux facteurs de forme remettent en cause cette hypothèse. Un appareil pliable peut modifier la taille et les proportions de son écran sans que la rotation de l'appareil ne change. Par exemple, le déploiement d'un appareil modifie le format, mais si l'utilisateur ne fait pas pivoter l'appareil, sa rotation reste la même. Si une application suppose que le rapport hauteur/largeur est corrélé à la rotation de l'appareil, elle peut faire pivoter ou mettre à l'échelle l'aperçu de la caméra de manière incorrecte. Il peut en être de même si une application suppose que l'orientation du capteur de l'appareil photo correspond à l'orientation portrait de l'appareil, ce qui n'est pas toujours le cas pour les appareils pliables en mode paysage.

Solution 1 : Jetpack CameraX (recommandée)

La solution la plus simple et la plus robuste consiste à utiliser la bibliothèque Jetpack CameraX. Son élément d'UI PreviewView est conçu pour gérer automatiquement toutes les complexités de l'aperçu :

  • PreviewView s'ajuste correctement à l'orientation du capteur, à la rotation de l'appareil et à la mise à l'échelle.
  • Il conserve le format de l'image de la caméra, généralement en la centrant et en la recadrant (FILL_CENTER).
  • Vous pouvez définir le type d'échelle sur FIT_CENTER pour mettre l'aperçu au format letterbox si nécessaire.

Pour en savoir plus, consultez Implémenter un aperçu dans la documentation CameraX.

Solution 2 : CameraViewfinder

Si vous utilisez une codebase Camera2 existante, la bibliothèque CameraViewfinder (rétrocompatible avec le niveau d'API 21) est une autre solution moderne. Il simplifie l'affichage du flux de la caméra en utilisant un TextureView ou un SurfaceView et en appliquant toutes les transformations nécessaires (ratio d'aspect, échelle et rotation) pour vous.

Pour en savoir plus, consultez l'article de blog Introducing Camera Viewfinder (Présentation du viseur de l'appareil photo) et le guide du développeur Aperçu de l'appareil photo.

Solution 3 : Implémentation manuelle de Camera2

Si vous ne pouvez pas utiliser CameraX ni CameraViewfinder, vous devez calculer manuellement l'orientation et le format, et vous assurer que les calculs sont mis à jour à chaque modification de la configuration :

  • Obtenez l'orientation du capteur de caméra (par exemple, 0, 90, 180 ou 270 degrés) à partir de CameraCharacteristics.
  • Obtenez la rotation actuelle de l'écran de l'appareil (par exemple, 0, 90, 180 ou 270 degrés).
  • Utilisez ces deux valeurs pour déterminer les transformations nécessaires pour votre SurfaceView ou TextureView.
  • Assurez-vous que le format de votre sortie Surface correspond à celui de l'aperçu de la caméra pour éviter toute distorsion.
  • Il est possible que l'application de l'appareil photo s'exécute sur une partie de l'écran, en mode multifenêtre ou fenêtrage du bureau, ou sur un écran connecté. Pour cette raison, la taille de l'écran ne doit pas être utilisée pour déterminer les dimensions du viseur de l'appareil photo. Utilisez plutôt les métriques de fenêtre.

Pour en savoir plus, consultez le guide du développeur Aperçu de l'appareil photo et la vidéo Votre application d'appareil photo sur différents facteurs de forme.

Solution 4 : Effectuer des actions de base sur l'appareil photo à l'aide d'un intent

Si vous n'avez pas besoin de nombreuses fonctionnalités de caméra, une solution simple et directe consiste à effectuer des actions de base sur la caméra, comme prendre une photo ou enregistrer une vidéo à l'aide de l'application de caméra par défaut de l'appareil. Vous n'avez pas besoin d'effectuer d'intégration avec une bibliothèque d'appareils photo. Utilisez plutôt un Intent.

Pour en savoir plus, consultez Intents de l'appareil photo.

Configuration et continuité

Les appareils pliables améliorent la polyvalence de l'UI, mais peuvent entraîner plus de modifications de configuration que les appareils non pliables. Votre application doit gérer ces modifications de configuration et leurs combinaisons, telles que la rotation de l'appareil, le pliage/dépliage et le redimensionnement de la fenêtre en mode multifenêtre ou bureau, tout en conservant ou en restaurant l'état de l'application. Par exemple, les applications doivent maintenir la continuité suivante :

  • État de l'application sans plantage ni changements perturbateurs pour les utilisateurs (par exemple, lors du changement d'écran ou de la mise en arrière-plan de l'application)
  • Position de défilement des champs à faire défiler
  • Texte saisi dans les champs de texte et état du clavier
  • Position de lecture du contenu multimédia pour que la lecture reprenne là où elle s'était arrêtée au moment du changement de configuration

Les modifications de configuration fréquemment déclenchées incluent screenSize, smallestScreenSize, screenLayout, orientation, density, fontScale, touchscreen et keyboard.

Consultez android:configChanges et Gérer les modifications de configuration. Pour en savoir plus sur la gestion de l'état de l'application, consultez Enregistrer les états de l'UI.

Modifications de la configuration de la densité

Les écrans extérieur et intérieur des appareils pliables à trois volets et des appareils pliables en mode paysage peuvent présenter des densités de pixels différentes. Par conséquent, la gestion du changement de configuration pour density nécessite une attention particulière. Android redémarre généralement l'activité lorsque la densité d'affichage change, ce qui peut entraîner une perte de données. Pour empêcher le système de redémarrer l'activité, déclarez la gestion de la densité dans votre fichier manifeste et gérez la modification de configuration de manière programmatique dans votre application.

Configuration d'AndroidManifest.xml

  • density : déclare que l'application gérera le changement de densité d'écran.
  • Autres modifications de configuration : il est également judicieux de déclarer d'autres modifications de configuration fréquentes, par exemple screenSize, orientation, keyboardHidden, fontScale, etc.

La déclaration de la densité (et d'autres modifications de configuration) empêche le système de redémarrer l'activité et appelle plutôt onConfigurationChanged().

Implémentation de onConfigurationChanged()

Lorsqu'un changement de densité se produit, vous devez mettre à jour vos ressources (par exemple, en rechargeant les bitmaps ou en recalculant les tailles de mise en page) dans le rappel :

  • Vérifiez que le DPI est passé à newConfig.densityDpi.
  • Réinitialiser les vues personnalisées, les drawables personnalisés, etc. à la nouvelle densité

Éléments de ressources à traiter

  • Ressource d'image : remplacez les bitmaps et les drawables par des ressources spécifiques à la densité, ou ajustez directement l'échelle.
  • Unité de mise en page (conversion dp en px) : recalculer la taille, la marge et la marge intérieure de la vue
  • Taille de la police et du texte : réappliquez la taille du texte en unité sp.
  • Dessin personnalisé View/Canvas : mettez à jour les valeurs basées sur les pixels utilisées pour dessiner Canvas.

Déterminer l'orientation de l'application

Ne vous fiez jamais à la rotation physique de l'appareil lorsque vous créez une application adaptative, car elle sera ignorée sur les appareils à grand écran. De plus, une application en mode multifenêtre peut avoir une orientation différente de celle de l'appareil. Utilisez plutôt Configuration.orientation ou WindowMetrics pour identifier si votre application est actuellement en orientation paysage ou portrait en fonction de la taille de la fenêtre.

Solution 1 : Utiliser Configuration.orientation

Cette propriété identifie l'orientation dans laquelle votre application est actuellement affichée.

Solution 2 : Utiliser WindowMetrics#getBounds()

Vous pouvez obtenir les limites d'affichage actuelles de l'application et vérifier sa largeur et sa hauteur pour déterminer l'orientation.

Si vous devez limiter l'orientation de l'application sur les téléphones (ou les écrans extérieurs des appareils pliables), mais pas sur les appareils à grand écran, consultez Limiter l'orientation de l'application sur les téléphones.

Postures et modes d'affichage

Les positions et états des appareils pliables, tels que la position sur table et HALF_OPENED, sont compatibles avec les appareils pliables verticaux et horizontaux. Toutefois, les dépliants ne sont pas compatibles avec la position sur table et ne peuvent pas être utilisés HALF_OPENED. Les appareils à trois volets offrent un écran plus grand pour une expérience utilisateur unique lorsqu'ils sont entièrement dépliés.

Pour différencier votre application sur les appareils pliables compatibles avec HALF_OPENED, utilisez les API Jetpack WindowManager telles que FoldingFeature.

Pour en savoir plus sur les postures et les états des appareils pliables, ainsi que sur la prise en charge de l'aperçu de l'appareil photo, consultez les guides du développeur suivants :

Les appareils pliables offrent des expériences de visionnage uniques. Les modes d'affichage arrière et Dual Screen vous permettent de proposer des fonctionnalités spéciales pour les appareils pliables, comme l'aperçu de selfie avec la caméra arrière, mais aussi d'afficher simultanément des contenus distincts sur l'écran intérieur et extérieur. Pour en savoir plus, consultez :

Verrouiller l'orientation sur l'orientation naturelle du capteur

Pour des cas d'utilisation très spécifiques (en particulier les applications qui doivent prendre le contrôle de l'intégralité de l'écran, indépendamment de l'état plié de l'appareil), l'indicateur nosensor vous permet de verrouiller l'application sur l'orientation naturelle de l'appareil. Par exemple, sur un Pixel Fold, l'orientation naturelle de l'appareil lorsqu'il est plié est portrait, tandis que l'orientation naturelle lorsqu'il est déplié est paysage. L'ajout du flag nosensor force l'application à être verrouillée en mode Portrait lorsqu'elle s'exécute sur l'écran extérieur et en mode Paysage lorsqu'elle s'exécute sur l'écran intérieur.

<activity
  android:name=".MainActivity"
  android:screenOrientation="nosensor">

Remappage des capteurs XR et des jeux

Pour les jeux et les applications XR, les données brutes des capteurs (comme le gyroscope ou l'accéléromètre) sont fournies dans le système de coordonnées fixe de l'appareil. Si l'utilisateur fait pivoter l'appareil pour jouer à un jeu en mode paysage, les axes du capteur ne pivotent pas avec l'écran, ce qui entraîne des commandes de jeu incorrectes.

Pour résoudre ce problème, vérifiez la valeur actuelle de Display.getRotation() et remappez les axes en conséquence :

  • Rotation 0 : x=x, y=y
  • Rotation 90 : x=-y, y=x
  • Rotation à 180° : x=-x, y=-y
  • Rotation 270 : x=y, y=-x

Pour les vecteurs de rotation (utilisés dans les applications de boussole ou de XR), utilisez SensorManager.remapCoordinateSystem() pour mapper la direction de l'objectif de la caméra ou le haut de l'écran aux nouveaux axes en fonction de la rotation actuelle.

Compatibilité des applications

Les applications doivent respecter les consignes relatives à la qualité des applications pour garantir la compatibilité avec tous les facteurs de forme et écrans connectés. Si une application ne peut pas respecter les consignes, les fabricants d'appareils peuvent implémenter des traitements de compatibilité, même si cela peut dégrader l'expérience utilisateur.

Pour en savoir plus, consultez la liste complète des solutions de contournement de la compatibilité fournies dans la plate-forme, en particulier celles liées à l'aperçu de la caméra, aux remplacements et aux modifications de l'API Android 16 qui pourraient modifier le comportement de votre application.

Pour en savoir plus sur la création d'applications adaptatives, consultez Qualité des applications sur grand écran.