Adopter des mises en page responsives pour votre interface utilisateur

Les applications Android doivent être compatibles avec un écosystème toujours plus vaste de facteurs de forme d'appareil. L'interface utilisateur d'une application doit être responsive afin de s'adapter à un large éventail de tailles d'écran, ainsi qu'à des orientations et des états d'appareil différents.

L'interface utilisateur responsive se concentre sur les principes de flexibilité et de continuité.

La flexibilité correspond aux mises en page qui utilisent de manière optimale l'espace disponible et qui s'ajustent en cas d'évolution de cet espace disponible. Les ajustements peuvent prendre différentes formes : simple augmentation de la taille d'une seule vue, repositionnement de vues pour les rendre plus accessibles, affichage ou masquage de vues supplémentaires, ou plusieurs de ces formes.

La continuité consiste à offrir une expérience utilisateur fluide lors de la transition d'une taille de fenêtre à une autre. Quelle que soit l'expérience choisie par l'utilisateur, elle doit se poursuivre sans interruption. Étant donné qu'un changement de taille peut entraîner la destruction et la recréation de toute la hiérarchie des vues, il est important que l'utilisateur ne perde pas sa place ni ses données.

Ce qu'il faut éviter

Évitez d'utiliser des valeurs physiques et matérielles pour prendre des décisions concernant la mise en page. Il peut être tentant de prendre des décisions en fonction d'une valeur fixe, mais dans de nombreux cas, ces valeurs ne sont pas utiles pour déterminer l'espace avec lequel votre interface utilisateur peut fonctionner.

Les applications peuvent redimensionner les fenêtres lorsqu'elles s'exécutent en mode multifenêtre, en mode Picture-in-picture ou dans des fenêtres de format libre, comme ChromeOS. Il peut même y avoir plusieurs écrans physiques, par exemple avec un appareil pliable ou doté de plusieurs écrans. Dans tous ces cas de figure, la taille physique de l'écran n'a pas d'importance pour déterminer comment afficher le contenu.

Plusieurs appareils affichant des fenêtres d'application de différentes tailles.
Figure 1 : La taille des fenêtres peut être différente de celle de l'appareil physique ou de l'écran.

Pour cette raison, évitez de verrouiller l'orientation ou le format de votre application. Même si l'appareil se trouve dans une orientation particulière, votre application peut être dans une orientation différente, uniquement en fonction de la taille de sa fenêtre. Par exemple, sur une tablette en mode paysage avec le mode multifenêtre, une application peut être en mode portrait, car elle est plus haute que large.

Évitez également d'essayer de déterminer si l'appareil est un téléphone ou une tablette. Qu'est-ce qui fait la spécificité d'une tablette ? C'est un concept subjectif. Sont-elles basées sur une taille ou un format précis ou sur une combinaison de tailles et de formats ? À mesure que de nouveaux facteurs de forme émergent, ces hypothèses peuvent changer et la distinction perd son importante.

Au lieu d'essayer l'une des stratégies précédentes, utilisez des points d'arrêt et des classes de taille de fenêtre.

Points d'arrêt et classes de taille de fenêtre

La partie réelle de l'écran allouée à votre application correspond à la fenêtre de l'application. Elle peut occuper la totalité ou une partie de l'écran. Vous devez donc utiliser la taille de la fenêtre lorsque vous prenez des décisions importantes concernant la mise en page de votre application.

Au moment de la rendre compatible avec plusieurs facteurs de forme, déterminez les valeurs de seuil où ces décisions importantes divergent. C'est pourquoi la grille de mise en page responsive de Material Design fournit des points d'arrêt pour la largeur et la hauteur, ce qui vous permet de mapper des tailles brutes dans des groupes distincts et normalisés qu'on appelle "classes de tailles de fenêtre". En raison de l'omniprésence du défilement vertical, la plupart des applications se focalisent surtout sur les classes de largeur. La plupart des applications peuvent donc être optimisées pour toutes les tailles d'écran en ne gérant que quelques points d'arrêt. (Pour en savoir plus sur les classes de taille de fenêtre, consultez Utiliser des classes de taille de fenêtre.)

Éléments permanents d'interface utilisateur

Les consignes de mise en page de Material Design définissent les paramètres régionaux des barres d'application, de la navigation et du contenu. Les deux premiers sont en général des éléments permanents d'interface utilisateur à la racine (ou très proches) de la hiérarchie des vues. Notez que ce terme ne signifie pas nécessairement que la vue est toujours visible, mais qu'elle reste en place pendant que d'autres vues de contenu peuvent être déplacées ou modifiées. Par exemple, un élément de navigation peut se trouver dans un panneau coulissant qui se retrouve en dehors de l'écran, mais toujours présent.

Les éléments permanents peuvent être responsifs et occupent généralement toute la largeur ou la hauteur de la fenêtre. Il est donc préférable d'utiliser des classes de taille pour décider de leur emplacement. Cela délimite l'espace restant pour le contenu. Dans l'aperçu suivant, l'activité utilise une barre inférieure pour les écrans compacts et une barre d'application supérieure pour les écrans plus grands. Les mises en page qualifiées utilisent des points d'arrêt en largeur, comme décrit précédemment.

<!-- res/layout/main_activity.xml -->

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- content view(s) -->

    <com.google.android.material.bottomappbar.BottomAppBar
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        ... />
</androidx.constraintlayout.widget.ConstraintLayout>


<!-- res/layout-w600dp/main_activity.xml -->
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        ... />

    <!-- content view(s) -->
</androidx.constraintlayout.widget.ConstraintLayout>

Contenu

Une fois que vous avez positionné les éléments permanents de l'interface utilisateur, allouez l'espace restant au contenu, en utilisant par exemple NavHostFragment avec le graphique de navigation de votre application. Pour en savoir plus, consultez Navigation pour les interfaces utilisateur responsives.

S'assurer que toutes les données sont compatibles avec différentes tailles

Aujourd'hui, la plupart des frameworks d'application utilisent un modèle de données distinct des composants Android qui contribuent à l'interface utilisateur (activités, fragments et vues). Avec Jetpack, ce rôle est généralement rempli par ViewModel, qui présente l'avantage supplémentaire d'être préservé en cas de changement de configuration. Pour en savoir plus, consultez Présentation de ViewModel.

Lorsque vous adoptez une mise en page qui s'adapte à différentes tailles, vous pourriez être tenté d'utiliser un autre modèle de données en fonction de la taille actuelle. Toutefois, cela va à l'encontre du principe du flux de données unidirectionnel. Les données doivent défiler vers le bas et "Vues", tandis que les événements comme les interactions des utilisateurs doivent défiler vers le haut. La création d'une dépendance pour changer ces directions, où le modèle de données dépend de la configuration de la couche de l'interface utilisateur, complique considérablement ce processus. Si l'application change de taille, vous devez prendre en compte la conversion d'un modèle de données à un autre.

Laissez votre modèle de données s'adapter à la classe de taille la plus grande. Vous pouvez ensuite choisir d'afficher, de masquer ou de repositionner le contenu dans l'interface utilisateur pour l'adapter à la classe de taille actuelle. Vous trouverez ci-dessous quelques stratégies à suivre pour déterminer le comportement de votre mise en page lors de la transition d'une classe de taille à une autre.

Développer le contenu

Mises en page standards : Flux

L'espace étendu peut être l'occasion d'agrandir simplement le contenu et de le reformater afin de le rendre plus accessible.

Agrandissez vos ensembles. De nombreuses applications affichent un ensemble d'éléments dans un conteneur à faire défiler tel que RecyclerView ou ScrollView. Autoriser un conteneur à augmenter automatiquement sa taille permet d'afficher davantage de contenu. Toutefois, veillez à ce que le contenu du conteneur ne soit pas étiré ni déformé à l'excès. Par exemple, pour un RecyclerView, envisagez d'utiliser un autre gestionnaire de mise en page comme GridLayoutManager, StaggeredGridLayoutManager ou FlexboxLayout lorsque la largeur n'est pas compacte.

Appareil plié et déplié qui illustre comment différents gestionnaires de mise en page présentent l&#39;application selon la classe de largeur.
Figure 2 : Différents gestionnaires de mise en page pour différentes classes de taille de fenêtre.

Les éléments individuels peuvent également utiliser une taille ou une forme différente pour afficher plus de contenu et distinguer plus facilement les limites des éléments.

Mettez en avant un élément principal. Si la mise en page est associée à un point focal spécifique, comme une image ou une vidéo, développez-le lorsque la fenêtre de l'application se développe pour maintenir l'attention de l'utilisateur. D'autres éléments associés peuvent être réorganisés autour ou en dessous de la vue principale.

Il existe de nombreuses façons d'organiser une telle mise en page, mais ConstraintLayout est particulièrement adapté à cet usage, car il propose de nombreuses manières de limiter la taille d'une vue enfant, en réduisant par exemple les proportions ou en appliquant un format, et de positionner ses enfants par rapport à lui-même ou aux autres enfants. Pour en savoir plus sur toutes ces fonctionnalités, consultez Créer une interface utilisateur responsive avec ConstraintLayout.

Affichez le contenu réductible par défaut. Si de l'espace est disponible, exposez du contenu qui, autrement, ne serait accessible qu'avec d'autres interactions de l'utilisateur, comme le clic, le défilement ou les gestes. Par exemple, le contenu qui apparaît dans une interface sous forme d'onglets peut être réorganisé sous forme de colonnes ou de liste lorsque davantage d'espace est disponible.

Étendez les marges. Si l'espace est si grand que vous ne trouvez pas de taille adaptée même après avoir utilisé tout votre contenu, étendez les marges de la mise en page pour que le contenu reste centré et que la taille de chaque vue et l'espace entre elles soient naturels.

Un composant plein écran peut également se transformer en interface utilisateur de boîte de dialogue flottante. Cela s'avère particulièrement utile lorsque ce composant requiert une attention exclusive pour effectuer une tâche utilisateur immédiate, comme la rédaction d'un e-mail ou la création d'un événement d'agenda.

Téléphone standard avec une boîte de dialogue en plein écran et téléphone pliable déplié avec la même boîte de dialogue sous forme de fenêtre flottante.
Figure 3 : Boîte de dialogue en plein écran transformée en boîte de dialogue standard de largeur moyenne et étendue.

Ajouter du contenu

Mises en page standards : panneau secondaire, vue Liste/Détails

Utilisez un volet secondaire. Un volet secondaire propose du contenu supplémentaire ou des actions contextuelles liées au contenu principal, comme les commentaires d'un document ou les éléments d'une playlist. Il s'affiche en général sur le tiers inférieur de l'écran en hauteur étendue ou sur le dernier tiers en largeur étendue.

Il importe de choisir l'emplacement du contenu si l'espace disponible est insuffisant pour afficher le volet. Voici quelques alternatives à explorer :

  • Panneau latéral sur le dernier bord avec DrawerLayout
  • Panneau inférieur avec BottomSheetBehavior
  • Menu ou fenêtre pop-up accessibles en appuyant sur une icône de menu
Figure 4 : Autres manières de présenter du contenu supplémentaire dans un volet secondaire.

Créez une mise en page à deux volets. Les grands écrans peuvent afficher une combinaison de fonctionnalités qui apparaissent normalement séparément sur les petits écrans. Dans de nombreuses applications, un modèle d'interaction courant consiste à afficher une liste d'éléments, comme les contacts ou les résultats de recherche, et à afficher les détails d'un élément lorsqu'il est sélectionné. Plutôt que d'agrandir la liste pour les écrans plus grands, utilisez la vue Liste/Détails pour afficher les deux fonctionnalités côte à côte dans une mise en page à deux volets. Contrairement à un volet secondaire, le volet des détails d'une vue Liste/Détails est un élément autonome qui peut s'afficher indépendamment sur les petits écrans.

Utilisez le widget dédié SlidingPaneLayout pour implémenter une vue Liste/Détails. Ce widget calcule automatiquement s'il y a assez d'espace pour afficher les deux volets en fonction de la valeur layout_width indiquée pour les deux volets. Les espaces restants peuvent être répartis à l'aide de layout_weight. S'il n'y a pas assez d'espace, chaque volet utilise toute la largeur de la mise en page. Le volet de détails glisse hors de l'écran ou en haut du volet de liste.

SlidingPaneLayout affichant les deux volets d&#39;une mise en page avec vue Liste/Détails sur un appareil disposant d&#39;un écran large.
Figure 5 : SlidingPaneLayout affichant deux volets en largeur étendue et un volet en largeur compacte.

Créer une mise en page à deux volets détaille l'utilisation de SlidingPaneLayout. Notez également que ce modèle peut avoir une incidence sur la structure de votre graphique de navigation (consultez la section Navigation pour les interfaces utilisateur responsives).

Ressources supplémentaires