Ajouter des mises en page adaptatives à une application Android basée sur les vues avec Compose

1. Avant de commencer

Il existe des appareils Android de différentes tailles et de différentes formes. Vous devez donc adapter votre application à diverses tailles d'écran afin de la rendre disponible pour différents utilisateurs et appareils avec un seul package Android (APK) ou Android App Bundle (AAB). Pour ce faire, au lieu de définir des dimensions statiques qui supposent une taille d'écran et un format donnés, vous devez proposer une mise en page responsive et adaptative pour votre application. Les mises en page adaptatives changent en fonction de l'espace disponible sur l'écran.

Cet atelier de programmation vous explique les principes de base pour créer des interfaces utilisateur adaptatives et adapter une application qui propose une liste de sports et des informations les concernant afin de la rendre compatible avec les appareils à grand écran. L'application de sport comporte trois écrans : "Accueil", "Favoris" et "Paramètres". L'écran d'accueil affiche une liste de sports et un espace réservé pour l'actualité sportive lorsque vous sélectionnez un sport dans la liste. Les écrans "Favoris" et "Paramètres" affichent également des espaces réservés. Pour changer d'écran, sélectionnez l'élément associé dans le menu de navigation en bas de l'écran.

Sur les grands écrans, l'application présente les problèmes de mise en page suivants :

  • Elle ne peut pas être utilisée en mode portrait.
  • Elle comporte de nombreux espaces vides.
  • Elle affiche toujours le menu de navigation en bas de l'écran.

Vous la rendrez adaptative, afin qu'elle :

  • soit compatible avec les modes paysage et portrait ;
  • affiche la liste de sports et l'actualité de chaque sport côte à côte, si l'espace horizontal est suffisant ;
  • affiche le composant de navigation conformément aux consignes Material Design.

Il s'agit d'une application à activité unique comportant plusieurs fragments. Vous utiliserez les fichiers suivants :

  • Le fichier AndroidManifest.xml, qui fournit des métadonnées sur l'application de sport.
  • Le fichier MainActivity.kt, qui contient un code généré avec le fichier activity_main.xml, l'annotation override, une classe enum qui représente les tailles en largeur de la fenêtre, ainsi qu'une définition de la méthode pour récupérer la classe de taille de fenêtre en largeur de l'application. Le menu de navigation en bas de l'écran est initialisé lorsque l'activité est créée.
  • Le fichier activity_main.xml, qui définit la mise en page par défaut pour l'activité Main.
  • Le fichier layout-sw600dp/activity_main.xml, qui définit une mise en page alternative pour l'activité Main. La mise en page alternative est appliquée lorsque la largeur de la fenêtre de l'application est supérieure ou égale à une valeur de 600dp. Au départ, son contenu est identique à la mise en page par défaut.
  • Le fichier SportsListFragment.kt contenant l'implémentation de la liste de sports et la navigation vers l'arrière personnalisée.
  • Le fichier fragment_sports_list.xml, qui définit une mise en page pour la liste de sports.
  • Le fichier navigation_menu.xml, qui définit les éléments du menu de navigation en bas de l'écran.

Dans une fenêtre de petite taille, l'application de sport affiche une liste de sports, accompagnée d'une barre de navigation en tant que composant de navigation supérieur. Dans une fenêtre de taille moyenne, elle affiche côte à côte une liste de sports et l'actualité sportive, ainsi qu'un rail de navigation en tant que composant de navigation supérieur. Enfin, dans une fenêtre de grande taille, elle affiche un panneau de navigation, une liste de sports et l'actualité sportive.

Figure 1. L'application de sport accepte plusieurs tailles de fenêtre avec un seul fichier APK ou AAB.

Conditions préalables

  • Vous disposez de connaissances de base en développement d'interfaces utilisateur basées sur les vues.
  • Vous maîtrisez la syntaxe Kotlin, y compris des fonctions lambda.
  • Vous avez terminé l'atelier de programmation Principes de base de Jetpack Compose.

Points abordés

  • Gérer les modifications de configuration
  • Ajouter des mises en page alternatives avec moins de modifications du code
  • Implémenter une interface utilisateur de vue détaillée qui se comporte différemment en fonction de la taille de la fenêtre

Objectifs de l'atelier

Créer une application Android compatible avec :

  • le mode paysage ;
  • les tablettes, les ordinateurs et les appareils mobiles ;
  • une vue détaillée qui s'adapte en fonction de la taille de l'écran.

Prérequis

2. Configuration

Téléchargez le code de cet atelier de programmation et configurez le projet :

  1. À partir de votre ligne de commande, clonez le code de ce dépôt GitHub :
$ git clone https://github.com/android/add-adaptive-layouts
  1. Dans Android Studio, ouvrez le projet AddingAdaptiveLayout. Le projet comporte plusieurs branches git :
  • main : contient le code de démarrage de ce projet. Vous allez modifier cette branche pour terminer l'atelier de programmation.
  • end : contient la solution de cet atelier de programmation.

3. Migrer le composant de navigation supérieur dans Compose

L'application de sport utilise un menu de navigation en bas de l'écran en tant que composant de navigation supérieur. Ce composant de navigation est implémenté avec la classe BottomNavigationView. Dans cette section, vous allez migrer le composant de navigation supérieur dans Compose.

Représenter le contenu de la ressource de menu associée en tant que classe scellée

  1. Créez une classe scellée MenuItem pour représenter le contenu du fichier navigation_menu.xml, puis transmettez-lui les paramètres iconId, labelId et destinationId.
  2. Ajoutez les objets Home, Favorite et Settings en tant que sous-classes correspondant à vos destinations.
sealed class MenuItem(
    // Resource ID of the icon for the menu item
    @DrawableRes val iconId: Int,
    // Resource ID of the label text for the menu item
    @StringRes val labelId: Int,
    // ID of a destination to navigate users
    @IdRes val destinationId: Int
) {

    object Home: MenuItem(
        R.drawable.ic_baseline_home_24,
        R.string.home,
        R.id.SportsListFragment
    )

    object Favorites: MenuItem(
        R.drawable.ic_baseline_favorite_24,
        R.string.favorites,
        R.id.FavoritesFragment
    )

    object Settings: MenuItem(
        R.drawable.ic_baseline_settings_24,
        R.string.settings,
        R.id.SettingsFragment
    )
}

Implémenter le menu de navigation en bas de l'écran en tant que fonction modulable

  1. Définissez une fonction modulable BottomNavigationBar qui comporte ces trois paramètres : un objet menuItems défini sur une valeur List<MenuItem>, un objet modifier défini sur une valeur Modifier = Modifier et un objet onMenuSelected défini sur une fonction lambda (MenuItem) -> Unit = {}.
  2. Dans le corps de la fonction modulable BottomNavigationBar, appelez une fonction NavigationBar() qui comporte un paramètre modifier.
  3. Dans la fonction lambda transmise à la fonction NavigationBar(), appelez la méthode forEach() sur le paramètre menuItems, puis la fonction NavigationBarItem() dans la fonction lambda définie sur l'appel de méthode foreach().
  4. Transmettez à la fonction NavigationBarItem() un paramètre selected défini sur false ; un paramètre onClick défini sur une fonction lambda contenant une fonction onMenuSelected avec un paramètre MenuItem ; un paramètre icon défini sur une fonction lambda contenant une fonction Icon qui comporte un paramètre painter = painterResource(id = menuItem.iconId) et contentDescription = null ; et enfin, un paramètre label défini sur une fonction lambda contenant une fonction Text qui comporte un paramètre (text = stringResource(id = menuItem.labelId).
@Composable
fun BottomNavigationBar(
    menuItems: List<MenuItem>,
    modifier: Modifier = Modifier,
    onMenuSelected: (MenuItem) -> Unit = {}
) {

    NavigationBar(modifier = modifier) {
        menuItems.forEach { menuItem ->
            NavigationBarItem(
                selected = false,
                onClick = { onMenuSelected(menuItem) },
                icon = {
                    Icon(
                        painter = painterResource(id = menuItem.iconId),
                        contentDescription = null)
                },
                label = { Text(text = stringResource(id = menuItem.labelId))}
            )
        }
    }
}

Remplacer l'élément BottomNavigationView par l'élément ComposeView dans le fichier de ressources de mise en page

  • Dans le fichier activity_main.xml, remplacez l'élément BottomNavigationView par l'élément ComposeView. Cela permet d'intégrer le composant de navigation en bas de l'écran dans une mise en page d'interface utilisateur basée sur les vues avec Compose.

activity_main.xml

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/nav_host_fragment_content_main"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toTopOf="@id/top_navigation"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navGraph="@navigation/nav_graph" />

        <androidx.compose.ui.platform.ComposeView
            android:id="@+id/navigation"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/top_navigation" />
    </androidx.constraintlayout.widget.ConstraintLayout>

Intégrer le menu de navigation en bas de l'écran basé sur Compose dans une mise en page d'interface utilisateur basée sur les vues

  1. Dans le fichier MainActivity.kt, définissez une variable navigationMenuItems définie sur une liste d'objets MenuItem. Les objets MenuItems s'affichent dans le menu de navigation en bas de l'écran dans l'ordre de la liste.
  2. Appelez la fonction BottomNavigationBar() pour intégrer le menu de navigation en bas de l'écran dans l'objet ComposeView.
  3. Accédez à la destination associée à l'élément sélectionné par l'utilisateur dans la fonction de rappel transmise à la fonction BottomNavigationBar.

MainActivity.kt

val navigationMenuItems = listOf(
    MenuItem.Home,
    MenuItem.Favorites,
    MenuItem.Settings
)

binding.navigation.setContent {
    MaterialTheme {
        BottomNavigationBar(menuItems = navigationMenuItems){ menuItem ->
            navController.navigate(screen.destinationId)
        }
    }
}

4. Prendre en charge l'orientation horizontale

Si votre application est compatible avec les appareils à grand écran, elle devrait prendre en charge les modes portrait et paysage. Pour le moment, votre application ne comporte qu'une seule activité : MainActivity.

L'orientation de l'écran de l'activité sur l'appareil est définie dans le fichier AndroidManifest.xml avec l'attribut android:screenOrientation, qui est défini sur la valeur portrait.

Pour rendre votre application compatible avec le mode paysage, procédez comme suit :

  1. Définissez la valeur de l'attribut android:screenOrientation sur fullUser. Cette configuration permet de verrouiller l'orientation de l'écran. L'orientation est déterminée par le capteur d'orientation de l'appareil pour l'une des quatre orientations possibles.

AndroidManifest.xml

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:screenOrientation="fullUser">

Pour que l'application de sport soit compatible avec le mode paysage, définissez la valeur fullUser sur l'attribut android:screenOrientation d'un élément d'activité dans le fichier AndroidManifest.xml.

Figure 2. Une fois le fichier AndroidManifest.xml modifié, l'application s'exécute en mode paysage.

5. Classes de taille de fenêtre

Il s'agit de valeurs de point d'arrêt qui permettent de classer les tailles de fenêtre en classes prédéfinies (petite, moyenne et grande) à partir de la taille de la fenêtre brute disponible pour votre application. Utilisez ces classes de taille pour concevoir, développer et tester votre mise en page adaptative.

La largeur et la hauteur disponibles sont traitées séparément afin que votre application soit toujours associée à deux classes de taille de fenêtre : une classe de taille en largeur et une classe de taille en hauteur.

Deux points d'arrêt séparent les trois classes de taille de fenêtre en largeur. Une valeur de 600 dp correspond au point d'arrêt séparant les classes de tailles petite et moyenne, tandis qu'une valeur de 840 dp correspond au point d'arrêt séparant les classes de tailles moyenne ou grande.

Figure 3. Classes de taille en largeur de la fenêtre et points d'arrêt associés.

Deux points d'arrêt séparent les trois classes de taille en hauteur de la fenêtre. Une valeur de 480 dp correspond au point d'arrêt séparant les classes de tailles petite ou moyenne, tandis qu'une valeur de 900 dp correspond au point d'arrêt séparant les classes de tailles moyenne ou grande.

Figure 4. Classes de taille en hauteur de la fenêtre et points d'arrêt associés.

Les classes de taille de fenêtre permettent de représenter la taille actuelle de la fenêtre de votre application. En d'autres termes, vous ne pouvez pas déterminer la classe de taille de la fenêtre par la taille physique de l'appareil. Même si votre application s'exécute sur le même appareil, la classe de taille de fenêtre associée change en fonction de la configuration, par exemple lorsque vous exécutez votre application en mode Écran partagé. Cela présente deux conséquences importantes :

  • Les appareils physiques ne permettent pas de déterminer une classe de taille de fenêtre spécifique.
  • La classe de taille de fenêtre peut varier tout au long de la durée de vie de votre application.

Une fois que vous avez ajouté des mises en page adaptatives à votre application, vous devez la tester dans une variété de tailles de fenêtre, en particulier dans les classes de tailles petite, moyenne et grande. S'il est nécessaire d'effectuer des tests pour chaque classe de taille de fenêtre, cela ne suffit pas dans de nombreux cas. Il est important de tester votre application dans différentes tailles de fenêtre afin de vous assurer que l'interface utilisateur s'adapte correctement. Pour en savoir plus, consultez Mises en pages pour les grands écrans et Qualité des applications sur grand écran.

6. Afficher les volets de liste et de vue détaillée côte à côte sur les grands écrans

Le fonctionnement de l'interface utilisateur de la vue détaillée peut devoir varier selon la classe de taille de fenêtre en largeur. Lorsque la classe de taille de fenêtre de largeur moyenne ou grande est associée à votre application, cela signifie que cette application dispose de suffisamment d'espace pour afficher les volets de liste et de vue détaillée côte à côte, afin que les utilisateurs puissent voir la liste des éléments et les informations détaillées de l'élément sélectionné sans transition d'écran. Cependant, la mise en page peut devenir trop encombrée sur les petits écrans. Il est alors préférable d'afficher un volet à la fois, à commencer par le volet de liste. Le volet de vue détaillée affiche les informations détaillées de l'élément sélectionné lorsque l'utilisateur appuie sur un élément de la liste. La classe SlidingPaneLayout gère la logique permettant de déterminer l'expérience utilisateur la plus adaptée à la taille de la fenêtre actuelle.

Configurer la mise en page du volet de liste

La classe SlidingPaneLayout est un composant d'interface utilisateur basé sur les vues. Vous allez modifier le fichier de ressources de mise en page pour le volet de liste, c'est-à-dire le fichier fragment_sports_list.xml dans cet atelier de programmation.

La classe SlidingPaneLayout comporte deux éléments enfants. Les attributs de largeur et de poids de chaque élément enfant sont les facteurs clés de la classe SlidingPaneLayout, permettant de déterminer si la fenêtre est suffisamment grande pour afficher les deux volets côte à côte. Dans le cas contraire, la liste en plein écran est remplacée par la vue détaillée en plein écran. La valeur des poids correspond à la taille proportionnelle des deux volets lorsque la taille de la fenêtre est supérieure à la configuration minimale requise pour afficher les volets côte à côte.

La classe SlidingPaneLayout a été appliquée au fichier fragment_sports_list.xml. Le volet de liste est configuré pour avoir une largeur de 1280dp. C'est la raison pour laquelle les volets de liste et de vue détaillée ne s'affichent pas côte à côte.

Faites en sorte que les volets s'affichent côte à côte lorsque la taille de l'écran dépasse une largeur de 580dp :

  • Définissez la valeur de RecyclerView sur une largeur de 280dp.

fragment_sports_list.xml

<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:id="@+id/sliding_pane_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SportsListFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="280dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clipToPadding="false"
        android:padding="8dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

    <androidx.fragment.app.FragmentContainerView
        android:layout_height="match_parent"
        android:layout_width="300dp"
        android:layout_weight="1"
        android:id="@+id/detail_container"
        android:name="com.example.android.sports.NewsDetailsFragment"/>
</androidx.slidingpanelayout.widget.SlidingPaneLayout>

Une fois que vous avez modifié le fichier sports_list_fragment.xml, l'application de sport affiche la liste des sports et l'actualité du sport sélectionné côte à côte.

Figure 5. Après avoir modifié le fichier de ressources de mise en page, les volets de liste et de vue détaillée s'affichent côte à côte.

Remplacer le volet de vue détaillée

Désormais, les volets de liste et de vue détaillée s'affichent côte à côte lorsque la classe de taille de fenêtre moyenne ou grande en largeur est associée à votre application. Cependant, l'écran passe au volet de vue détaillée lorsque les utilisateurs sélectionnent un élément dans le volet de liste.

L'application effectue une transition d'écran pour afficher uniquement l'actualité sportive, alors que l'application devrait continuer d'afficher la liste des sports et l'actualité sportive côte à côte.

Figure 6. Une fois que vous avez sélectionné un sport dans la liste, l'écran passe au volet de vue détaillée.

Ce problème est dû à la navigation déclenchée lorsque l'utilisateur sélectionne un élément dans le volet de liste. Le code approprié est disponible dans le fichier SportsListFragment.kt.

SportsListFragment.kt

val adapter = SportsAdapter {
    sportsViewModel.updateCurrentSport(it)
    // Navigate to the details pane.
    val action =
       SportsListFragmentDirections.actionSportsListFragmentToNewsFragment()
    this.findNavController().navigate(action)
}

Assurez-vous que l'écran ne passe au volet de vue détaillée que lorsque l'espace disponible est insuffisant pour afficher les volets de liste et de vue détaillée côte à côte :

  • Dans la variable de la fonction adapter, ajoutez une instruction if qui vérifie si l'attribut isSlidable de la classe SlidingPaneLayout est défini sur "true" et si l'attribut isOpen de la classe SlidingPaneLayout est défini sur "false".

SportsListFragment.kt

val adapter = SportsAdapter {
    sportsViewModel.updateCurrentSport(it)
    if(slidingPaneLayout.isSlidable && !slidingPaneLayout.isOpen){
        // Navigate to the details pane.
        val action =
           SportsListFragmentDirections.actionSportsListFragmentToNewsFragment()
        this.findNavController().navigate(action)
    }
}

7. Choisir le composant de navigation approprié en fonction de la classe de taille de fenêtre en largeur

Selon Material Design, votre application doit sélectionner les composants de manière adaptative. Dans cette section, vous allez choisir un composant de navigation pour la barre de navigation supérieure en fonction de la classe de taille de fenêtre en largeur actuelle. Le tableau suivant indique le composant de navigation attendu pour chaque classe de taille de fenêtre :

Classe de taille de fenêtre en largeur

Composant de navigation

Petite

Navigation inférieure

Moyenne

Rail de navigation

Grande

Panneau de navigation permanent

Implémenter le rail de navigation

  1. Créez une fonction modulable NavRail() comportant trois paramètres : un objet menuItems défini sur une valeur List<MenuItem>, un objet modifier défini sur une valeur Modifier et une fonction lambda onMenuSelected.
  2. Dans le corps de la fonction, appelez une fonction NavigationRail() qui accepte l'objet modifier en tant que paramètre.
  3. Appelez une fonction NavigationRailItem() pour chaque objet MenuItem dans l'objet menuItems comme vous l'avez fait pour la fonction NavigationBarItem dans la fonction BottomNavigationBar().

Implémenter le panneau de navigation permanent

  1. Créez une fonction modulable NavigationDrawer() comportant ces trois paramètres : un objet menuItems défini sur une valeur List<MenuItem>, un objet modifier défini sur une valeur Modifier et une fonction lambda onMenuSelected.
  2. Dans le corps de la fonction, appelez une fonction Column() qui accepte l'objet modifier en tant que paramètre.
  3. Appelez une fonction Row() pour chaque objet MenuItem dans l'objet menuItems.
  4. Dans le corps de la fonction Row(), ajoutez les libellés icon et text comme vous l'avez fait pour la fonction NavigationBarItem dans la fonction BottomNavigationBar().

Choisir le composant de navigation approprié en fonction de la classe de taille de fenêtre en largeur

  1. Pour récupérer la classe de taille de fenêtre en largeur actuelle, appelez la fonction rememberWidthSizeClass() dans la fonction modulable transmise à la méthode setContent() sur l'objet ComposeView.
  2. Créez une branche conditionnelle pour choisir le composant de navigation en fonction de la classe de taille de fenêtre en largeur récupérée, puis appelez la classe sélectionnée.
  3. Transmettez un objet Modifier à la fonction NavigationDrawer pour spécifier sa largeur en tant que valeur 256dp.

ActivityMain.kt

binding.navigation.setContent {
    MaterialTheme {
        when(rememberWidthSizeClass()){
            WidthSizeClass.COMPACT ->
                BottomNavigationBar(menuItems = navigationMenuItems){ menuItem ->
                    navController.navigate(screen.destinationId)
                }
            WidthSizeClass.MEDIUM ->
                NavRail(menuItems = navigationMenuItems){ menuItem ->
                    navController.navigate(screen.destinationId)
                }
            WidthSizeClass.EXPANDED ->
                NavigationDrawer(
                    menuItems = navigationMenuItems,
                    modifier = Modifier.width(256.dp)
                ) { menuItem ->
                    navController.navigate(screen.destinationId)
                }
        }

    }
}

Placer le composant de navigation à la bonne position

Votre application peut désormais choisir le composant de navigation approprié en fonction de la classe de taille de fenêtre en largeur actuelle, mais les composants sélectionnés ne peuvent pas être placés comme prévu. En effet, l'élément ComposeView est placé sous l'élément FragmentViewContainer.

Modifiez la ressource de mise en page alternative pour la classe MainActivity :

  1. Ouvrez le fichier layout-sw600dp/activity_main.xml.
  2. Modifiez la contrainte pour positionner les éléments ComposeView et FragmentContainer horizontalement.

layout-sw600dp/activity_main.xml

  <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/nav_host_fragment_content_main"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintLeft_toRightOf="@+id/top_navigation"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:navGraph="@navigation/nav_graph" />

        <androidx.compose.ui.platform.ComposeView
            android:id="@+id/top_navigation"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/top_navigation" />
    </androidx.constraintlayout.widget.ConstraintLayout>

Une fois la modification effectuée, l'application choisit le composant de navigation approprié en fonction de la classe de taille de fenêtre en largeur associée. La première capture d'écran montre l'écran pour la classe de taille de fenêtre de largeur moyenne. La seconde montre celui pour la classe de taille de fenêtre de largeur agrandie.

Lorsqu'elle est associée à la classe de taille de fenêtre de largeur moyenne, l'application de sport affiche le rail de navigation, la liste des sports et l'actualité sportive. Lorsqu'elle est associée à la classe de taille de fenêtre de largeur agrandie, elle affiche le panneau de navigation, la liste des sports et l'actualité sportive sur l'écran d'accueil.

Figure 7. Écrans pour les classes de taille de fenêtre de largeur moyenne et agrandie.

8. Félicitations

Félicitations ! Vous avez terminé cet atelier de programmation et appris à ajouter des mises en page adaptatives à une application Android basée sur les vues avec Compose. Vous avez ainsi découvert la classe SlidingPaneLayout, les classes de taille de fenêtre et la sélection du composant de navigation en fonction de la classe de taille de fenêtre en largeur.

En savoir plus