Les développeurs rencontrent souvent des difficultés uniques lorsqu'ils créent des applications pour les appareils pliables, en particulier pour les appareils tels que le Samsung Trifold ou le Pixel Fold d'origine, qui s'ouvre au format paysage (rotation_0 = paysage). Les erreurs des développeurs incluent les suivantes :
- Hypothèses incorrectes sur l'orientation de l'appareil
- Cas d'utilisation ignorés
- Échec du recalcul ou de la mise en cache des valeurs lors des modifications de configuration
Les problèmes spécifiques liés à l'appareil incluent les suivants :
- Incohérence dans l'orientation naturelle de l'appareil entre les écrans de couverture et intérieur (hypothèses basées sur rotation_0 = portrait), ce qui entraîne l'échec des applications lors du pliage et du dépliage
- Différentes densités d'écran et gestion incorrecte des modifications de configuration density
- Problèmes d'aperçu de l'appareil photo causés par la dépendance du capteur de l'appareil photo à 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.
- Mettez à jour les aperçus de l'appareil photo pour gérer correctement l'orientation de l'appareil et les proportions, éviter les aperçus latéraux et empêcher les images étirées ou recadrées.
- Maintenez la continuité de l'application lors du pliage ou du dépliage de l'appareil en
conservant l'état avec
ViewModelou des approches similaires, ou en gérant manuellement les modifications de la densité de l'écran et de l'orientation, ce qui évite les redémarrages de l'application ou la perte d'état. - Pour les applications utilisant 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 applications adaptatives, elle devrait bien fonctionner sur les appareils pliables. Sinon, avant de vérifier les détails spécifiques des appareils pliables à trois volets et des appareils pliables en mode paysage, consultez les concepts de base suivants concernant le développement adaptatif Android.
Mises en page adaptatives
Votre interface utilisateur doit gérer non seulement différentes tailles d'écran, mais également les modifications en temps réel des proportions, telles que le dépliage et le passage en mode multifenêtre ou en mode fenêtre de bureau. Pour en savoir plus sur la façon de procéder, consultez À propos des mises en page adaptatives :
- 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'interface utilisateur de votre application
- Simplifier l'implémentation des mises en page canoniques, telles que la liste détaillée, à l'aide des API Jetpack
Classes de taille de fenêtre
Les appareils pliables, y compris les appareils pliables en mode paysage et les appareils à 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.
L'exemple suivant utilise la bibliothèque adaptative Material 3 pour déterminer l'espace disponible pour 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()
val windowSizeClass = adaptiveInfo.windowSizeClass
when {
windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_EXPANDED_LOWER_BOUND) -> // Expanded
windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_MEDIUM_LOWER_BOUND) -> // Medium
else -> // Compact
}
Pour en savoir plus, consultez Utiliser des classes de taille de fenêtre.
Qualité des applications adaptatives
Le respect du niveau 2 (application adaptative optimisée) ou du niveau 1 (application adaptative différenciée) des consignes relatives à la qualité des applications adaptatives garantit que votre application offre une expérience utilisateur attrayante sur les appareils à trois volets, les appareils pliables en mode paysage et autres appareils à grand écran. Les consignes couvrent les vérifications critiques sur plusieurs niveaux pour passer d'une application adaptative à une expérience différenciée.
Android 16 ou version ultérieure
Pour les applications ciblant Android 16 (niveau d'API 36) ou version ultérieure, 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é au format letterbox n'est plus utilisé.
Considérations particulières
Les appareils à trois volets et les appareils pliables en mode paysage introduisent des comportements matériels uniques qui nécessitent une gestion spécifique, en particulier en ce qui concerne les capteurs, l'aperçu de l'appareil photo 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 les calculs de format (dans des scénarios tels que le mode multifenêtre, le mode fenêtre de bureau ou les écrans connectés) se produit lorsque l'aperçu de l'appareil photo apparaît étiré, latéral, 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).
Les nouveaux facteurs de forme remettent en question cette hypothèse. Un appareil pliable peut modifier la taille de son écran et son format sans que la rotation de l'appareil ne change. Par exemple, le dépliage 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 format est corrélé à la rotation de l'appareil, elle peut faire pivoter ou mettre à l'échelle l'aperçu de l'appareil photo de manière incorrecte. La même chose peut se produire 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
PreviewView élément d'interface utilisateur est conçu pour gérer automatiquement toutes les complexités de l'aperçu
:
PreviewViews'ajuste correctement à l'orientation du capteur, à la rotation de l'appareil et à la mise à l'échelle.- Il conserve le format de l'image de l'appareil photo, généralement en la centrant et en la recadrant (FILL_CENTER).
- Vous pouvez définir le type d'échelle sur
FIT_CENTERpour 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 base de code Camera2 existante, la bibliothèque CameraViewfinder (rétrocompatible avec le niveau d'API 21) est une autre solution moderne. Elle simplifie l'affichage du flux de l'appareil photo en utilisant un TextureView ou un SurfaceView et en appliquant toutes les transformations nécessaires (format, échelle et rotation).
Pour en savoir plus, consultez l'article de blog Introducing Camera Viewfinder (Présentation du viseur de l'appareil photo) et Camera preview (Aperçu de l'appareil photo) du guide du développeur.
Solution 3 : Implémentation manuelle de Camera2
Si vous ne pouvez pas utiliser CameraX ou CameraViewfinder, vous devez calculer manuellement l'orientation et le format, et vous assurer que les calculs sont mis à jour à chaque modification de configuration :
- Obtenez l'orientation du capteur de l'appareil photo (par exemple, 0, 90, 180, 270 degrés) à partir de
CameraCharacteristics. - Obtenez la rotation actuelle de l'écran de l'appareil (par exemple, 0, 90, 180, 270 degrés).
- Utilisez ces deux valeurs pour déterminer les transformations nécessaires pour votre
SurfaceViewouTextureView. - Assurez-vous que le format de votre
Surfacede sortie correspond à celui de l'aperçu de l'appareil photo pour éviter toute distorsion. - L'application d'appareil photo peut s'exécuter dans une partie de l'écran, en mode multifenêtre ou en mode fenêtre de 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 la 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 l'appareil photo, une solution simple consiste à effectuer des actions de base sur l'appareil photo, comme prendre une photo ou enregistrer une vidéo à l'aide de l'application Appareil photo 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'interface utilisateur, 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 en mode 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 modification perturbatrice pour les utilisateurs (par exemple, lors du changement d'écran ou de l'envoi de l'application en arrière-plan)
- Position de défilement des champs à faire défiler
- Texte saisi dans les champs et état du clavier
- Position de lecture des contenus multimédias 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'interface utilisateur.
Modifications de la configuration de la densité
Les écrans extérieur et intérieur des appareils à trois volets et des appareils pliables en mode paysage peuvent présenter des densités de pixels différentes. Par conséquent, la gestion de la modification 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 par programmation dans votre application.
Configuration AndroidManifest.xml
density: déclare que l'application gérera la modification de la densité de l'écran- Autres modifications de configuration : il est également recommandé 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'une modification de la densité se produit, vous devez mettre à jour vos ressources (par exemple, en rechargeant des bitmaps ou en recalculant les tailles de mise en page) dans le rappel :
- Vérifiez que le DPI est passé à
newConfig.densityDpi. - Réinitialisez les vues personnalisées, les drawables personnalisés, etc. à la nouvelle densité.
Éléments de ressource à 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 de la vue, la marge, remplissage.
- 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 dessinerCanvas
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 et 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 mode 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.
Positions et modes d'affichage
Les positions et états pliables tels que la position sur table et HALF_OPENED sont
compatibles avec les appareils pliables en mode portrait et en mode paysage. Toutefois, les appareils à trois volets ne sont pas compatibles avec la position sur table et ne peuvent pas être utilisés en mode HALF_OPENED. Les appareils à trois volets offrent plutôt un écran plus grand pour une expérience utilisateur unique lorsqu'ils sont complètement 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 positions, les états et la compatibilité avec l'aperçu de l'appareil photo des appareils pliables, consultez les guides du développeur suivants :
En matière d'affichage, les appareils pliables offrent des expériences 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 occuper tout l'écran, quel que soit 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 le mode portrait, tandis que l'orientation naturelle lorsqu'il est déplié est le mode paysage. L'ajout de l'indicateur 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 pour les jeux et la XR
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 le Display.getRotation() actuel 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 l'appareil photo ou le haut de l'écran sur les 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é sur tous les facteurs de forme et les écrans connectés. Si une application ne peut pas respecter les consignes, les fabricants d'appareils peuvent implémenter des traitements de compatibilité, bien que cela puisse dégrader l'expérience utilisateur.
Pour en savoir plus, consultez la liste complète des solutions de contournement de compatibilité fournies dans la plate-forme, en particulier celles liées à l'aperçu de l'appareil photo, 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 les consignes relatives à la qualité des applications adaptatives.