Afficher le contenu bord à bord dans les vues

Essayer Compose
Jetpack Compose est le kit d'outils d'interface utilisateur recommandé pour Android. Découvrez comment utiliser le mode bord à bord dans Compose.

Une fois que vous ciblez le SDK 35 ou une version ultérieure sur un appareil équipé d'Android 15 ou version ultérieure, votre application s'affiche en mode bord à bord. La fenêtre s'étend sur toute la largeur et la hauteur de l'écran en s'affichant derrière les barres système. Les barres système incluent la barre d'état, la barre de légende et la barre de navigation.

De nombreuses applications comportent une barre d'application supérieure. Elle doit s'étendre jusqu'au bord supérieur de l'écran et s'afficher derrière la barre d'état. Elle peut également être réduite à la hauteur de la barre d'état lorsque le contenu défile.

De nombreuses applications comportent également une barre d'application inférieure ou une barre de navigation inférieure. Ces barres doivent également s'étendre jusqu'au bord inférieur de l'écran et s'afficher derrière la barre de navigation. Sinon, les applications doivent afficher le contenu défilant derrière la barre de navigation.

Figure 1 : Barres système dans une mise en page bord à bord.

Lorsque vous implémentez une mise en page bord à bord dans votre application, tenez compte des points suivants :

  1. Activer l'affichage de bord à bord
  2. Implémenter des mises en page adaptatives pour optimiser l'expérience utilisateur sur différents formats
  3. Gérer les chevauchements visuels
  4. Envisager d'afficher des voiles derrière les barres système
Exemple d'image derrière la barre d'état
Figure 2. Exemple d'image derrière la barre d'état.

Activer l'affichage de bord à bord

Si votre application cible le SDK 35 ou une version ultérieure, le mode bord à bord est automatiquement activé pour les appareils Android 15 ou version ultérieure.

Pour activer le mode bord à bord sur les versions précédentes d'Android, appelez manuellement enableEdgeToEdge dans onCreate de votre Activity.

Kotlin

 override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         WindowCompat.enableEdgeToEdge(window)
        ...
      }

Java

 @Override
      protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WindowCompat.enableEdgeToEdge(getWindow());
        ...
      }

Par défaut, enableEdgeToEdge() rend les barres système transparentes, sauf en mode de navigation à trois boutons, où la barre de navigation reçoit un voile translucide. Les couleurs des icônes système et du voile sont ajustées en fonction du thème clair ou sombre du système.

Pour activer l'affichage de bord à bord dans votre application sans utiliser la enableEdgeToEdge() fonction, consultez Configurer manuellement l'affichage de bord à bord.

Gérer les chevauchements à l'aide d'encarts

Certaines vues de votre application peuvent s'afficher derrière les barres système, comme illustré dans la figure 3.

Vous pouvez résoudre les chevauchements en réagissant aux encarts, qui spécifient les parties de l'écran qui croisent l'interface utilisateur du système, comme la barre de navigation ou la barre d'état. L'intersection peut signifier un affichage au-dessus du contenu, mais elle peut également informer votre application sur les gestes système.

Les types d'encarts qui s'appliquent à l'affichage de votre application en mode bord à bord sont les suivants :

  • Encarts de barres système : ils sont plus adaptés aux vues sur lesquelles vous pouvez appuyer et qui ne doivent pas être masquées visuellement par les barres système.

  • Encarts d'encoche : ils sont destinés aux zones où l'écran peut être découpé en raison de la forme de l'appareil.

  • Encarts de gestes système : ils sont destinés aux zones de navigation par gestes utilisées par le système et qui sont prioritaires sur votre application.

Encarts de barres système

Les encarts de barres système sont le type d'encarts le plus couramment utilisé. Ils représentent la zone où l'interface utilisateur du système s'affiche sur l'axe Z au-dessus de votre application. Ils sont plus adaptés pour déplacer ou ajouter des marges intérieures aux vues de votre application sur lesquelles vous pouvez appuyer et qui ne doivent pas être masquées visuellement par les barres système.

Par exemple, le bouton d'action flottant (BAF) de la figure 3 est partiellement masqué par la barre de navigation :

Exemple d'implémentation bord à bord, mais la barre de navigation recouvre le bouton d'action flottant
Figure 3. Barre de navigation qui chevauche un BAF dans une mise en page bord à bord.

Pour éviter ce type de chevauchement visuel en mode gestes ou en mode boutons, vous pouvez augmenter les marges de la vue à l'aide de getInsets(int) avec WindowInsetsCompat.Type.systemBars().

L'exemple de code suivant montre comment implémenter des encarts de barres système :

Kotlin

ViewCompat.setOnApplyWindowInsetsListener(fab) { v, windowInsets ->
  val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
  // Apply the insets as a margin to the view. This solution sets
  // only the bottom, left, and right dimensions, but you can apply whichever
  // insets are appropriate to your layout. You can also update the view padding
  // if that's more appropriate.
  v.updateLayoutParams<MarginLayoutParams> {
      leftMargin = insets.left
      bottomMargin = insets.bottom
      rightMargin = insets.right
  }

  // Return CONSUMED if you don't want the window insets to keep passing
  // down to descendant views.
  WindowInsetsCompat.CONSUMED
}

Java

ViewCompat.setOnApplyWindowInsetsListener(fab, (v, windowInsets) -> {
  Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
  // Apply the insets as a margin to the view. This solution sets only the
  // bottom, left, and right dimensions, but you can apply whichever insets are
  // appropriate to your layout. You can also update the view padding if that's
  // more appropriate.
  MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
  mlp.leftMargin = insets.left;
  mlp.bottomMargin = insets.bottom;
  mlp.rightMargin = insets.right;
  v.setLayoutParams(mlp);

  // Return CONSUMED if you don't want the window insets to keep passing
  // down to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

Si vous appliquez cette solution à l'exemple illustré dans la figure 3, vous n'obtiendrez aucun chevauchement visuel en mode boutons, comme illustré dans la figure 4 :

Barre de navigation translucide ne couvrant pas le bouton d&#39;action flottant
Figure 4. Résolution du chevauchement visuel en mode boutons.

Il en va de même pour le mode de navigation par gestes, comme illustré dans la figure 5 :

bord à bord avec la navigation par gestes
Figure 5. Résolution du chevauchement visuel en mode de navigation par gestes.

Encarts d'encoche

Certains appareils sont dotés d'une encoche. En règle générale, l'encoche se trouve en haut de l'écran et est incluse dans la barre d'état. Lorsque l'écran de l'appareil est en mode paysage, l'encoche peut se trouver sur le bord vertical. Selon le contenu que votre application affiche à l'écran, vous devez implémenter une marge intérieure pour éviter les encoches, car par défaut, les applications s'affichent dans l'encoche.

Par exemple, de nombreux écrans d'application affichent une liste d'éléments. Ne masquez pas les éléments de la liste avec l'encoche ou les barres système.

Kotlin

ViewCompat.setOnApplyWindowInsetsListener(binding.recyclerView) { v, insets ->
  val bars = insets.getInsets(
    WindowInsetsCompat.Type.systemBars()
      or WindowInsetsCompat.Type.displayCutout()
  )
  v.updatePadding(
    left = bars.left,
    top = bars.top,
    right = bars.right,
    bottom = bars.bottom,
  )
  WindowInsetsCompat.CONSUMED
}

Java

ViewCompat.setOnApplyWindowInsetsListener(mBinding.recyclerView, (v, insets) -> {
  Insets bars = insets.getInsets(
    WindowInsetsCompat.Type.systemBars()
    | WindowInsetsCompat.Type.displayCutout()
  );
  v.setPadding(bars.left, bars.top, bars.right, bars.bottom);
  return WindowInsetsCompat.CONSUMED;
});

Déterminez la valeur de WindowInsetsCompat en prenant le ou logique des barres système et des types d'encoches.

Définissez clipToPadding sur RecyclerView afin que la marge intérieure défile avec les éléments de la liste. Cela permet aux éléments de passer derrière les barres système lorsque l'utilisateur fait défiler la liste, comme illustré dans l'exemple suivant.

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

Encarts de gestes système

Les encarts de gestes système représentent les zones de la fenêtre où les gestes système sont prioritaires sur votre application. Ces zones sont affichées en orange dans la figure 6 :

Exemple d&#39;encarts de gestes système
Figure 6. Encarts de gestes système.

Comme pour les encarts de barres système, vous pouvez éviter de chevaucher les encarts de gestes système à l'aide de getInsets(int) avec WindowInsetsCompat.Type.systemGestures().

Utilisez ces encarts pour déplacer ou ajouter des marges intérieures aux vues que vous pouvez balayer sur les bords. Les cas d'utilisation courants incluent les feuilles inférieures, le balayage dans les jeux et les carrousels implémentés à l'aide de ViewPager2.

Sur Android 10 ou version ultérieure, les encarts de gestes système contiennent un encart inférieur pour le geste d'accueil, ainsi qu'un encart gauche et droit pour les gestes de retour :

Exemple de mesures d&#39;encart de geste système
Figure 7. Mesures des encarts de gestes système.

L'exemple de code suivant montre comment implémenter des encarts de gestes système :

Kotlin

ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets ->
    val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures())
    // Apply the insets as padding to the view. Here, set all the dimensions
    // as appropriate to your layout. You can also update the view's margin if
    // more appropriate.
    view.updatePadding(insets.left, insets.top, insets.right, insets.bottom)

    // Return CONSUMED if you don't want the window insets to keep passing down
    // to descendant views.
    WindowInsetsCompat.CONSUMED
}

Java

ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> {
    Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures());
    // Apply the insets as padding to the view. Here, set all the dimensions
    // as appropriate to your layout. You can also update the view's margin if
    // more appropriate.
    view.setPadding(insets.left, insets.top, insets.right, insets.bottom);

    // Return CONSUMED if you don't want the window insets to keep passing down
    // to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

Composants Material

De nombreux composants Material Android basés sur des vues (com.google.android.material) gèrent automatiquement les encarts, y compris BottomAppBar, BottomNavigationView, NavigationRailView et NavigationView

Toutefois, AppBarLayout ne gère pas automatiquement les encarts. Ajoutez android:fitsSystemWindows="true" pour gérer les encarts supérieurs.

Découvrez comment gérer les encarts avec les composants Material dans Compose.

Distribution d'encarts rétrocompatible

Pour arrêter la distribution d'encarts aux vues enfants et éviter un remplissage excessif, vous pouvez consommer des encarts à l'aide de la WindowInsetsCompat.CONSUMED constante. Toutefois, sur les appareils équipés d'Android 10 (niveau d'API 29 et versions antérieures), les encarts ne sont pas distribués aux éléments frères après l'appel de WindowInsetsCompat.CONSUMED, ce qui peut entraîner un chevauchement visuel involontaire.

Exemple de répartition des encarts cassés
Figure 8. Exemple de distribution d'encarts incorrecte. Les encarts ne sont pas distribués aux vues frères après que ViewGroup 1 consomme des encarts sur Android 10 (niveau d'API 29) et versions antérieures, ce qui entraîne le chevauchement de TextView 2 avec la barre de navigation du système. Toutefois, les encarts sont distribués aux vues frères sur Android 11 (niveau d'API 30) et versions ultérieures, comme prévu.

Pour vérifier que les encarts sont distribués aux éléments frères pour toutes les versions d'Android compatibles, utilisez ViewGroupCompat#installCompatInsetsDispatch avant de consommer des encarts, disponible sur AndroidX Core et Core-ktx 1.16.0-alpha01 et versions ultérieures.

Kotlin

// Use the i.d. assigned to your layout's root view, e.g. R.id.main
val rootView = findViewById(R.id.main)
// Call before consuming insets
ViewGroupCompat.installCompatInsetsDispatch(rootView)

Java

// Use the i.d. assigned to your layout's root view, e.g. R.id.main
LinearLayout rootView = findViewById(R.id.main);
// Call before consuming insets
ViewGroupCompat.installCompatInsetsDispatch(rootView);
Exemple de répartition des encarts fixes
Figure 9. Distribution d'encarts corrigée après l'appel de ViewGroupCompat#installCompatInsetsDispatch.

Mode immersif

Certains contenus sont plus adaptés au plein écran, ce qui offre à l'utilisateur une expérience plus immersive. Vous pouvez masquer les barres système pour le mode immersif à l'aide des WindowInsetsController et WindowInsetsControllerCompat bibliothèques :

Kotlin

val windowInsetsController =
      WindowCompat.getInsetsController(window, window.decorView)

// Hide the system bars.
windowInsetsController.hide(Type.systemBars())

// Show the system bars.
windowInsetsController.show(Type.systemBars())

Java

Window window = getWindow();
WindowInsetsControllerCompat windowInsetsController =
      WindowCompat.getInsetsController(window, window.getDecorView());
if (windowInsetsController == null) {
    return;
  }
// Hide the system bars.
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars());

// Show the system bars.
windowInsetsController.show(WindowInsetsCompat.Type.systemBars());

Pour en savoir plus sur l'implémentation de cette fonctionnalité, consultez Masquer les barres système pour le mode immersif.

Icônes de barre système

L'appel de enableEdgeToEdge garantit que les couleurs des icônes de la barre système sont mises à jour lorsque le thème de l'appareil change.

Lorsque vous passez en mode bord à bord, vous devrez peut-être mettre à jour manuellement les couleurs des icônes de la barre système afin qu'elles contrastent avec l'arrière-plan de votre application. Par exemple, pour créer des icônes de barre d'état claires :

Kotlin

WindowCompat.getInsetsController(window, window.decorView)
    .isAppearanceLightStatusBars = false

Java

WindowCompat.getInsetsController(window, window.getDecorView())
    .setAppearanceLightStatusBars(false);

Protection de la barre système

Une fois que votre application cible le SDK 35 ou une version ultérieure, le mode bord à bord est appliqué. La barre d'état du système et les barres de navigation par gestes sont transparentes, mais la barre de navigation à trois boutons est translucide. Appelez enableEdgeToEdge pour rendre cette fonctionnalité rétrocompatible.

Toutefois, les paramètres par défaut du système peuvent ne pas fonctionner dans tous les cas d'utilisation. Consultez les conseils de conception des barres système Android et la conception bord à bord pour déterminer si vous devez utiliser des barres système transparentes ou translucides.

Créer des barres système transparentes

Créez une barre d'état transparente en ciblant Android 15 (SDK 35) ou version ultérieure, ou en appelant enableEdgeToEdge() avec des arguments par défaut pour les versions antérieures.

Créez une barre de navigation par gestes transparente en ciblant Android 15 ou version ultérieure, ou en appelant enableEdgeToEdge() avec des arguments par défaut pour les versions antérieures. Pour la barre de navigation à trois boutons, définissez Window.setNavigationBarContrastEnforced sur false. Sinon, un voile translucide sera appliqué.

Créer des barres système translucides

Pour créer une barre d'état translucide, procédez comme suit :

  1. Mettez à jour votre dépendance androidx-core vers la version 1.16.0-beta01 ou ultérieure.
  2. Encapsulez votre mise en page XML dans androidx.core.view.insets.ProtectionLayout et attribuez-lui un ID.
  3. Accédez par programmation à ProtectionLayout pour définir des protections, en spécifiant le côté et un GradientProtection pour la barre d'état.

<androidx.core.view.insets.ProtectionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_protection"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ScrollView
        android:id="@+id/item_list"
        android:clipToPadding="false"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!--items-->

    </ScrollView>

</androidx.core.view.insets.ProtectionLayout>

findViewById<ProtectionLayout>(R.id.list_protection)
    .setProtections(
        listOf(
            GradientProtection(
                WindowInsetsCompat.Side.TOP,
                // Ideally, this is the pane's background color
                paneBackgroundColor
            )
        )
    )

Assurez-vous que le ColorInt transmis à GradientProtection correspond à l'arrière-plan du contenu. Par exemple, une mise en page liste-détails affichée sur un appareil pliable peut avoir différents GradientProtections de différentes couleurs pour le panneau de liste et le panneau de détails.

Figure 1 : Protection de dégradé de différentes couleurs.

Ne créez pas de barre de navigation par gestes translucide. Pour créer une barre de navigation à trois boutons translucide, procédez de l'une des manières suivantes :

  • Si votre mise en page est déjà encapsulée dans un ProtectionView, vous pouvez transmettre un ColorProtection ou un GradientProtection supplémentaire à la méthode setProtections. Avant de le faire, assurez-vous que window.isNavigationBarContrastEnforced = false.
  • Sinon, définissez window.isNavigationBarContrastEnforced = true.

Autres conseils

Conseils supplémentaires pour la gestion des encarts.

Afficher le contenu défilant en mode bord à bord

Vérifiez que le dernier élément de la liste n'est pas masqué par les barres système dans votre RecyclerView ou NestedScrollView en gérant les encarts et en définissant clipToPadding sur false.

La vidéo suivante montre un RecyclerView avec l'affichage de bord à bord désactivé (à gauche) et activé (à droite) :

Consultez les extraits de code dans la section Créer des listes dynamiques avec RecyclerView pour obtenir un exemple de code.

Afficher les boîtes de dialogue en plein écran en mode bord à bord

Pour afficher les boîtes de dialogue en plein écran en mode bord à bord, appelez enableEdgeToEdge sur la boîte de dialogue.

Kotlin

class MyAlertDialogFragment : DialogFragment() {
    override fun onStart(){
        super.onStart()
        dialog?.window?.let { WindowCompat.enableEdgeToEdge(it) }
    }
    ...
}

Java

public class MyAlertDialogFragment extends DialogFragment {
    @Override
    public void onStart() {
        super.onStart();
        Dialog dialog = getDialog();
        if (dialog != null) {
            Window window = dialog.getWindow();
            if (window != null) {
                WindowCompat.enableEdgeToEdge(window);
            }
        }
    }
    ...
}

Ressources supplémentaires

Consultez les références suivantes pour en savoir plus sur le mode bord à bord.

Blogs

Design

Autres documents

Vidéos