Design responsif/adaptatif avec vues

Les mises en page responsives et adaptatives offrent une expérience utilisateur optimisée, quelle que soit la taille de l'écran. Implémentez des mises en page responsives/adaptatives pour permettre à votre application basée sur les vues de prendre en charge toutes les tailles, orientations et configurations d'affichage, y compris les configurations redimensionnables telles que le mode multifenêtre.

Responsive design

La première étape pour prendre en charge divers facteurs de forme d'appareil consiste à créer une mise en page qui s'adapte aux variations de l'espace d'affichage disponible pour votre application.

ConstraintLayout

Le meilleur moyen de créer une mise en page responsive consiste à utiliser ConstraintLayout comme mise en page de base de votre interface utilisateur. ConstraintLayout vous permet de spécifier la position et la taille de chaque vue en fonction des relations spatiales avec les autres vues de la mise en page. Toutes les vues peuvent ensuite être déplacées et redimensionnées ensemble à mesure que l'espace d'affichage change.

Le moyen le plus simple de créer une mise en page avec ConstraintLayout consiste à utiliser l'éditeur de mise en page dans Android Studio. L'éditeur de mise en page vous permet de faire glisser de nouvelles vues dans la mise en page, d'appliquer des contraintes relatives aux vues parentes et sœurs, et de définir des propriétés de vue, le tout sans modifier manuellement le code XML.

Figure 3 : Éditeur de mise en page dans Android Studio affichant un ConstraintLayout.

Pour en savoir plus, consultez la section Créer une interface utilisateur responsive avec ConstraintLayout.

Largeur et hauteur responsives

Pour vous assurer que votre mise en page s'adapte à différentes tailles d'écran, utilisez wrap_content, match_parent ou 0dp (match constraint) pour la largeur et la hauteur des composants de la vue au lieu des valeurs codées en dur:

  • wrap_content: la taille de la vue est définie en fonction de son contenu.
  • match_parent: la vue s'étend autant que possible dans la vue parent.
  • 0dp (match constraint): dans un ConstraintLayout, semblable à match_parent. La vue occupe tout l'espace disponible en respectant ses contraintes.

Par exemple :

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

La figure 4 montre comment la largeur et la hauteur de TextView s'ajustent lorsque la largeur de l'écran change en fonction de l'orientation de l'appareil.

Figure 4 : TextView responsif.

TextView définit sa largeur pour occuper tout l'espace disponible (match_parent) et sa hauteur à exactement l'espace requis par la hauteur du texte contenu (wrap_content), ce qui permet à la vue de s'adapter à différentes dimensions d'affichage et différentes quantités de texte.

Si vous utilisez un LinearLayout, vous pouvez également développer les vues enfants en fonction de la pondération de la mise en page afin qu'elles occupent proportionnellement l'espace disponible. Cependant, l'utilisation des pondérations dans un élément LinearLayout imbriqué nécessite que le système effectue plusieurs passes de mise en page pour déterminer la taille de chaque vue, ce qui ralentit les performances de l'interface utilisateur.

ConstraintLayout peut créer presque toutes les mises en page possibles avec LinearLayout, sans impact sur les performances. Vous devez donc convertir votre LinearLayout imbriqué en ConstraintLayout. Vous pouvez ensuite définir des mises en page pondérées à l'aide de chaînes de contraintes.

Design adaptatif

La mise en page de votre application doit toujours s'adapter aux différentes tailles d'écran. Toutefois, même une mise en page responsive ne peut pas offrir la meilleure expérience utilisateur possible sur tous les appareils ou sur tous les écrans en mode multifenêtre. Par exemple, l'interface utilisateur que vous avez conçue pour un téléphone n'offre probablement pas une expérience utilisateur optimale sur une tablette. La conception adaptative propose d'autres mises en page optimisées pour différentes dimensions d'affichage.

SlidingPaneLayout pour les interfaces utilisateur détaillées en liste

Une interface utilisateur détaillée en liste offre généralement une expérience utilisateur différente sur des écrans de différentes tailles. Sur les grands écrans, les volets de liste et de détail sont généralement côte à côte. Lorsqu'un élément de la liste est sélectionné, les informations le concernant s'affichent dans le volet des détails sans modifier l'interface utilisateur. Les deux volets restent côte à côte. Toutefois, sur les petits écrans, les deux volets s'affichent séparément, chacun occupant la totalité de la zone d'affichage. Lorsqu'un élément est sélectionné dans le volet de liste, le volet de vue détaillée (contenant les informations de l'élément sélectionné) remplace le volet de liste. Le bouton de navigation arrière remplace le volet de détails par la liste.

SlidingPaneLayout gère la logique permettant de déterminer laquelle des deux expériences utilisateur est adaptée à la taille de fenêtre actuelle:

<?xml version="1.0" encoding="utf-8"?>
<androidx.slidingpanelayout.widget.SlidingPaneLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="280dp"
        android:layout_height="match_parent"
        android:layout_gravity="start" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        app:defaultNavHost="true"
        app:navGraph="@navigation/item_navigation" />

</androidx.slidingpanelayout.widget.SlidingPaneLayout>

Les attributs layout_width et layout_weight des deux vues contenues dans SlidingPaneLayout déterminent le comportement de SlidingPaneLayout. Dans l'exemple, si la fenêtre est suffisamment grande (au moins 580 dp) pour afficher les deux vues, les volets sont affichés côte à côte. Toutefois, si la largeur de la fenêtre est inférieure à 580 dp, les volets se glissent les uns sur les autres pour occuper individuellement la totalité de la fenêtre de l'application.

Si la largeur de la fenêtre est supérieure à la largeur minimale totale spécifiée (580 dp), les valeurs layout_weight peuvent être utilisées pour dimensionner proportionnellement les deux volets. Dans cet exemple, le volet de liste a toujours une largeur de 280 dp, car il n'a pas de pondération. Toutefois, le volet de détails remplit toujours tout espace horizontal au-delà de 580 dp en raison du paramètre layout_weight de la vue.

Autres ressources de mise en page

Pour adapter la conception de l'interface utilisateur à des tailles d'écran très variables, utilisez d'autres mises en page identifiées par des qualificatifs de ressource.

Figure 5 : La même application utilisant différentes mises en page pour différentes tailles d'écran.

Vous pouvez fournir des mises en page adaptatives et propres à l'écran en créant des répertoires res/layout/ supplémentaires dans le code source de votre application. Créez un répertoire pour chaque configuration d'écran qui nécessite une mise en page différente. Ajoutez ensuite un qualificatif de configuration d'écran au nom du répertoire layout (par exemple, layout-w600dp pour les écrans dont la largeur disponible est de 600 dp).

Les qualificatifs de configuration représentent l'espace d'affichage visible disponible pour l'interface utilisateur de votre application. Le système prend en compte toutes les décorations du système (telles que la barre de navigation) et les modifications de configuration des fenêtres (telles que le mode multifenêtre) lors de la sélection de la mise en page de votre application.

Pour créer d'autres mises en page dans Android Studio, consultez Utiliser des variantes de mise en page pour optimiser différents écrans dans Développer une UI avec des vues.

Qualificatif de plus petite largeur

Le qualificatif de taille d'écran plus petite largeur vous permet de fournir d'autres mises en page pour les écrans dont la largeur minimale est mesurée en pixels indépendants de la densité (dp).

En décrivant la taille de l'écran comme une mesure de dp, Android vous permet de créer des mises en page conçues pour des dimensions d'affichage spécifiques, sans vous soucier des différentes densités de pixels.

Par exemple, vous pouvez créer une mise en page nommée main_activity optimisée pour les téléphones et les tablettes en créant différentes versions du fichier dans différents répertoires:

res/layout/main_activity.xml           # For phones (smaller than 600dp smallest width)
res/layout-sw600dp/main_activity.xml   # For 7" tablets (600dp wide or wider)

Le qualificatif de largeur la plus petite spécifie le plus petit des deux côtés de l'écran, quelle que soit l'orientation actuelle de l'appareil. Il s'agit donc d'un moyen de spécifier la taille d'affichage globale disponible pour votre mise en page.

Voici comment les autres valeurs de largeur minimale correspondent aux tailles d'écran classiques :

  • 320 dp: petit écran de téléphone (240 x 320 ldpi, 320 x 480 mdpi, 480 x 800 hdpi, etc.)
  • 480 dp : grand écran de téléphone d'environ 5 pouces (480 x 800 mdpi)
  • 600 dp: tablette 7 pouces (600 x 1 024 mdpi)
  • 720 dp: tablette de 10 pouces (720 x 1 280 mdpi, 800 x 1 280 mdpi, etc.)

La figure suivante montre plus en détail comment différentes largeurs de dp d'écran correspondent à différentes tailles et orientations d'écran.

Figure 6. Points d'arrêt en largeur recommandés pour accepter différentes tailles d'écran.

Les valeurs du qualificatif de plus petite largeur sont dp, car ce qui compte est la quantité d'espace d'affichage disponible une fois que le système a pris en compte la densité de pixels (et non la résolution brute en pixels).

Les tailles que vous spécifiez à l'aide de qualificatifs de ressource (par exemple, la plus petite largeur) ne correspondent pas aux tailles d'écran réelles. Les tailles spécifient plutôt la largeur ou la hauteur en dp disponibles dans la fenêtre de votre application. Le système Android peut utiliser une partie de l'écran pour l'interface utilisateur du système (comme la barre système en bas de l'écran ou la barre d'état en haut). Il est donc possible qu'une partie de l'écran ne soit pas disponible pour votre mise en page. Si votre application est utilisée en mode multifenêtre, elle n'a accès qu'à la taille de la fenêtre qui la contient. Lorsque la fenêtre est redimensionnée, une modification de configuration est déclenchée avec la nouvelle taille de fenêtre, ce qui permet au système de sélectionner un fichier de mise en page approprié. Par conséquent, les tailles des qualificatifs de ressource que vous déclarez ne doivent spécifier que l'espace nécessaire à votre application. Le système prend en compte tout espace utilisé par l'interface utilisateur du système lorsqu'il fournit de l'espace pour votre mise en page.

Qualificatif de largeur disponible

Au lieu de modifier la mise en page en fonction de la plus petite largeur d'écran, vous pouvez la modifier en fonction de la largeur ou de la hauteur disponible. Par exemple, vous pouvez utiliser une mise en page à deux volets chaque fois que l'écran fournit une largeur d'au moins 600 dp, qui peut changer selon que l'appareil est en mode paysage ou portrait. Dans ce cas, vous devez utiliser le qualificatif largeur disponible comme suit:

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

Si la hauteur disponible est problématique pour votre application, vous pouvez utiliser le qualificatif hauteur disponible. Par exemple, layout-h600dp pour les écrans dont la hauteur d'écran est d'au moins 600 dp.

Qualificatifs d'orientation

Même si vous pouvez accepter toutes les variantes de taille en n'utilisant que des combinaisons des qualificatifs plus petite largeur et largeur disponible, vous pouvez également modifier l'expérience utilisateur lorsque l'utilisateur passe du mode portrait au mode paysage, et inversement.

Pour ce faire, vous pouvez ajouter les qualificatifs port ou land aux noms de votre répertoire de mise en page. Assurez-vous simplement que les qualificatifs d'orientation sont placés après les qualificatifs de taille. Par exemple :

res/layout/main_activity.xml                # For phones
res/layout-land/main_activity.xml           # For phones in landscape
res/layout-sw600dp/main_activity.xml        # For 7" tablets
res/layout-sw600dp-land/main_activity.xml   # For 7" tablets in landscape

Pour en savoir plus sur tous les qualificatifs de configuration d'écran, consultez la section Présentation des ressources d'application.

Classes de taille de fenêtre

Les classes de taille de fenêtre sont des points d'arrêt de fenêtre d'affichage qui vous aident à créer des mises en page adaptatives. Les points d'arrêt identifient la zone d'affichage disponible pour votre application comme étant compacte, moyenne ou étendue. La largeur et la hauteur sont spécifiées séparément. Votre application dispose donc toujours d'une classe de taille de fenêtre pour la largeur et d'une classe de taille de fenêtre pour la hauteur.

Pour appliquer des mises en page adaptatives de manière programmatique, procédez comme suit:

  • Créer des ressources de mise en page basées sur les points d'arrêt de classe de taille de fenêtre
  • Calculez les classes de taille de fenêtre de largeur et de hauteur de votre application à l'aide de la fonction WindowSizeClass#compute() de la bibliothèque Jetpack WindowManager.
  • Gonfler la ressource de mise en page pour les classes de taille de fenêtre actuelles

Pour en savoir plus sur les classes de taille de fenêtre, consultez Assurer la compatibilité avec différentes tailles d'écran.

Composants d'interface utilisateur modulaires à l'aide de fragments

Lorsque vous concevez votre application pour plusieurs tailles d'affichage, utilisez des fragments pour extraire votre logique d'UI dans des composants distincts. Vous vous assurez ainsi de ne pas dupliquer inutilement le comportement de l'interface utilisateur entre les activités. Vous pouvez ensuite combiner des fragments pour créer des mises en page à plusieurs volets sur les grands écrans, ou placer des fragments dans des activités distinctes sur les petits écrans.

Par exemple, le schéma détaillé en liste (voir SlidingPaneLayout ci-dessus) peut être implémenté avec un fragment contenant la liste et un autre contenant les détails des éléments de la liste. Sur les grands écrans, les fragments peuvent s'afficher côte à côte. Sur les petits écrans, chaque fragment remplit individuellement l'écran.

Pour en savoir plus, consultez la présentation des fragments.

Intégration d'activités

Si votre application se compose de plusieurs activités, l'intégration d'activités vous permet de créer facilement une UI adaptative.

L'intégration d'activités affiche plusieurs activités ou plusieurs instances de la même activité simultanément dans la fenêtre de tâches d'une application. Sur les grands écrans, les activités peuvent être affichées côte à côte. Sur les petits écrans, elles sont empilées les unes sur les autres.

Pour déterminer la manière dont votre application affiche ses activités, créez un fichier de configuration XML que le système utilisera pour déterminer la présentation appropriée en fonction de la taille d'affichage. Vous pouvez également effectuer des appels de l'API Jetpack WindowManager.

L'intégration d'activités est compatible avec les changements d'orientation des appareils et les appareils pliables, qui empilent et dépilent les activités lorsque l'appareil pivote, ou se plie et se déplie.

Pour en savoir plus, consultez la section Intégration d'activités.

Tailles d'écran et formats

Testez votre application sur des tailles d'écran et des formats variés pour vous assurer que l'interface utilisateur s'adapte correctement.

Android version 10 (niveau d'API 29) ou ultérieure est compatible avec de nombreux formats. Les facteurs de forme pliables peuvent aller de grands écrans étroits (par exemple, 21:9 lorsqu'ils sont pliés) à un format carré de 1:1 lorsqu'ils sont dépliés.

Pour assurer la compatibilité avec autant d'appareils que possible, testez vos applications pour un maximum des formats d'écran suivants:

Figure 7. Différents formats d'écran.

Si vous n'avez pas accès à des appareils pour toutes les tailles d'écran que vous souhaitez tester, vous pouvez utiliser Android Emulator pour émuler presque toutes les tailles d'écran.

Si vous préférez effectuer un test sur un appareil réel, mais que vous ne l'avez pas en votre possession, vous pouvez utiliser Firebase Test Lab pour accéder aux appareils dans un centre de données Google.

Ressources supplémentaires