FrameLayout : concepts clés, positionnement simple dans Android

Auteur : IT Sectr Publié le : 2026-02-24 Temps de lecture : 8 min

Découvrez les concepts clés de FrameLayout — la ViewGroup la plus simple du SDK Android, conçue pour héberger un seul élément enfant (généralement) ou superposer plusieurs éléments les uns sur les autres. FrameLayout est pratique pour les conteneurs placeholder, les fragments, les indicateurs de chargement et les éléments de premier plan. Il ne gère pas le positionnement des enfants — chaque élément suivant est dessiné par-dessus le précédent, et leur position est déterminée par layout_gravity (left, top, right, bottom, center). Les scénarios de base sont décrits dans la Référence API FrameLayout.

Points clés

  • Superposition de couches — FrameLayout place les éléments séquentiellement les uns sur les autres ; le dernier déclaré en XML se dessine le plus haut.
  • Premier plan — l'attribut android:foreground permet de superposer un drawable sur tous les éléments enfants, utile pour les effets et le masquage.
  • measureAllChildren — par défaut, FrameLayout mesure tous les enfants, même invisibles (GONE). Le désactiver accélère le dessin de 20 à 60 %.
  • layout_gravity — la seule façon de positionner un élément enfant dans FrameLayout : top, bottom, left, right, center.
  • Utilisation avec Fragment — FrameLayout est le conteneur standard pour FragmentTransaction.replace(), remplaçant le contenu sans recréer l'activité.

Qu'est-ce que FrameLayout ?

FrameLayout est la ViewGroup la plus simple du SDK Android, conçue pour bloquer une zone de l'écran et afficher une seule vue enfant (ou en superposer plusieurs). Contrairement à LinearLayout (disposition séquentielle) et RelativeLayout (positionnement relatif), FrameLayout ne modifie pas les positions des enfants — chaque nouvel enfant est placé dans le coin supérieur gauche (0,0) par défaut et dessiné par-dessus le précédent.

FrameLayout a été introduit dans l'API Level 1 et reste le conteneur Android le plus léger : il ne remplace pas onMeasure par une logique complexe et effectue un nombre minimal d'opérations de layout. Selon Android Performance Blog, FrameLayout exécute onLayout en un seul passage et n'ajoute pratiquement aucun surcoût par rapport au placement direct d'une View. Cela en fait un choix idéal pour les conteneurs où la vitesse compte : layouts d'éléments RecyclerView (associés à ConstraintLayout pour le positionnement), conteneurs de fragments, couches de superposition.

La taille de FrameLayout est déterminée par défaut par le plus grand élément enfant (si match_parent n'est pas défini). Si aucun enfant n'est spécifié, FrameLayout se réduit à (0,0). L'attribut android:measureAllChildren (section ci-dessous) modifie ce comportement.

FrameLayout dans la hiérarchie ViewGroup Android

FrameLayout hérite de ViewGroup et est le parent direct de nombreux conteneurs spécialisés : FragmentContainerView (fragments), CardView (cartes avec ombre), ScrollView (enfant unique), NestedScrollView. Lors de la création d'une Activity avec navigation par fragments, le modèle standard d'Android Studio utilise FrameLayout (ou FragmentContainerView) comme conteneur racine pour les fragments.

Premier plan et measureAllChildren

android:foreground — un attribut FrameLayout qui spécifie un drawable dessiné par-dessus tous les éléments enfants. Contrairement à background (sous les enfants), foreground s'affiche au-dessus du contenu et peut être transparent. Il est utilisé pour : les effets de superposition au toucher (ripple via ?attr/selectableItemBackground), le masquage d'images, l'affichage d'indicateurs d'état (coche de sélection sur une image).

Foreground prend en charge les ressources drawable standard : ColorDrawable, ShapeDrawable, RippleDrawable, LayerDrawable. Depuis l'API 23+, android:foregroundGravity est disponible pour le positionnement du premier plan (fill, center, top, bottom). En mode remplissage (fill), le foreground s'étend sur tout le FrameLayout ; en mode centre, il se dessine au centre.

android:measureAllChildren — un attribut booléen (true par défaut) qui détermine si tous les éléments enfants doivent être mesurés lors du calcul de la taille de FrameLayout. Si true (par défaut), FrameLayout prend en compte les tailles de tous les enfants, y compris GONE (avec une taille de 0). Si false, FrameLayout mesure uniquement les enfants VISIBLE et INVISIBLE — les éléments GONE sont exclus du calcul. Selon Google I/O 2019, désactiver measureAllChildren pour les conteneurs avec de nombreux éléments GONE (par exemple, les listes à visibilité alternée) accélère le dessin initial de 20 à 60 %.

layout_gravity : positionnement dans FrameLayout

android:layout_gravity — un attribut d'un élément enfant de FrameLayout (et d'autres ViewGroups) qui définit sa position à l'intérieur du conteneur. Dans FrameLayout, layout_gravity est le seul moyen de contrôler la position d'un élément enfant, car FrameLayout ne fournit pas ses propres règles de positionnement (comme RelativeLayout) ni de direction (comme LinearLayout).

Valeurs possibles : top, bottom, left, right, center, center_horizontal, center_vertical, fill, fill_horizontal, fill_vertical, clip_horizontal, clip_vertical. Combinées via | : android:layout_gravity="bottom|center_horizontal" — l'élément est fixé au bord inférieur et centré horizontalement. Pour les éléments plus petits que FrameLayout, layout_gravity détermine leur position dans l'espace libre.

Si layout_gravity n'est pas défini, l'élément est placé dans le coin supérieur gauche (top|left) par défaut. Pour un FrameLayout contenant plusieurs enfants, chacun peut avoir son propre layout_gravity — un élément peut être dans le coin supérieur gauche, un autre dans le coin inférieur droit, un troisième centré. Cela permet de créer des superpositions simples (par exemple, une icône de fermeture sur une image).

Différence : gravity vs layout_gravity

android:gravity (attribut parent) aligne le contenu à l'intérieur de FrameLayout — par exemple, le texte dans un TextView. android:layout_gravity (attribut enfant) aligne l'élément lui-même à l'intérieur de FrameLayout. Dans le contexte de FrameLayout, gravity définit comment les enfants sont positionnés par défaut (similaire à layout_gravity pour tous les enfants à la fois), mais le layout_gravity de chaque élément spécifique remplace la valeur parente.

Exemples : XML et cas d'utilisation

Exemple 1 : Superposition de base — Étiquette sur image

Une image avec une étiquette de texte dans le coin inférieur droit. FrameLayout contient un ImageView remplissant l'écran et un TextView avec layout_gravity="bottom|end" pour le positionnement sur l'image.

xml
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="200dp">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/product_photo"
        android:scaleType="centerCrop" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="8dp"
        android:background="@drawable/badge_background"
        android:elevation="2dp"
        android:paddingHorizontal="8dp"
        android:paddingVertical="4dp"
        android:text="-30%"
        android:textColor="@android:color/white"
        android:textSize="14sp"
        android:textStyle="bold" />

</FrameLayout>

ImageView remplit tout le FrameLayout (hauteur 200dp). Le TextView avec layout_gravity="bottom|end" est placé dans le coin inférieur droit sur l'image. elevation=2dp ajoute une ombre sous l'étiquette, la séparant visuellement de l'image. Cet exemple minimal aurait nécessité un conteneur imbriqué ou du code personnalisé dans LinearLayout.

Exemple 2 : Indicateur de chargement (barre de progression sur le contenu)

Un écran avec du contenu et une barre de progression centrée qui apparaît pendant le chargement. FrameLayout contient deux éléments : le contenu et un ProgressBar avec visibility="gone" (basculé dans le code).

xml
<FrameLayout
    android:id="@+id/content_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/content_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Contenu chargé"
        android:textSize="18sp" />

    <ProgressBar
        android:id="@+id/loading_spinner"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_gravity="center"
        android:visibility="gone" />

</FrameLayout>

La ProgressBar est masquée par défaut (gone). Au début du chargement, findViewById(R.id.loading_spinner).visibility = View.VISIBLE est appelé — le spinner apparaît centré sur le contenu. Après le chargement — .visibility = View.GONE. FrameLayout assure la superposition sans déplacer la position du contenu — le texte ne bouge pas lorsque le spinner apparaît, car la ProgressBar se dessine par-dessus.

Exemple 3 : Conteneur de Fragment

FrameLayout comme conteneur standard pour FragmentTransaction. L'activité remplace les fragments à l'intérieur de ce conteneur selon la navigation.

xml
<FrameLayout
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
kotlin
import androidx.fragment.app.FragmentTransaction

val fragmentContainer = R.id.fragment_container

fun navigateTo(fragment: Fragment) {
    supportFragmentManager
        .beginTransaction()
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
        .replace(fragmentContainer, fragment)
        .addToBackStack(null)
        .commit()
}

FrameLayout comme conteneur de fragments est le moyen le plus léger de prendre en charge la navigation par fragments. FragmentContainerView (une sous-classe de FrameLayout) est recommandé avec Navigation Component 2.4+, mais un simple FrameLayout reste valide pour les FragmentTransactions manuelles. L'avantage clé est que FragmentTransaction.replace() remplace complètement le contenu sans affecter l'Activity.

Quand utiliser FrameLayout

FrameLayout est optimal pour quatre scénarios : conteneur de fragments (FragmentContainerView ou FrameLayout), superposition de chargement (ProgressBar sur le contenu), étiquettes de cartes (étiquette sur image), conteneur placeholder pour ViewStub (chargement différé).

Ne convient pas pour : le positionnement complexe de plusieurs éléments (utilisez ConstraintLayout), les listes séquentielles (LinearLayout ou RecyclerView), les layouts dynamiques avec changement d'ordre des éléments.

FrameLayout comme élément racine de l'écran — mauvaise pratique si l'écran contient plus de 2 à 3 éléments. Pour un conteneur racine, utilisez ConstraintLayout — il offre plus de contrôle sur le positionnement sans perte de performances. Utilisez FrameLayout uniquement pour les blocs enfants où une superposition ou un placeholder est nécessaire.

Foire aux questions

Quelle est la différence entre FrameLayout et ConstraintLayout ?

FrameLayout — un conteneur minimaliste sans système de positionnement (uniquement layout_gravity), conçu pour la superposition d'éléments. ConstraintLayout — un système de layout complet avec contraintes, chaînes, barrières, dimensions en pourcentage et support de MotionLayout. FrameLayout est plus rapide pour les cas simples (1 enfant ou superposition) ; ConstraintLayout est nécessaire pour les layouts complexes. Choix : FrameLayout pour la superposition de chargement et le conteneur de fragments ; ConstraintLayout pour tout le reste.

Comment faire en sorte que FrameLayout n'occupe que la place du plus grand enfant ?

Définissez la taille de FrameLayout sur wrap_content sur l'axe souhaité (android:layout_width="wrap_content" et/ou android:layout_height="wrap_content"). FrameLayout s'ajustera alors à la taille du plus grand élément enfant. Si tous les enfants sont plus petits que FrameLayout, l'espace excédentaire reste vide. Pour un contrôle précis, utilisez match_parent avec un padding fixe.

Pourquoi les éléments dans FrameLayout se chevauchent-ils ?

C'est le comportement prévu de FrameLayout — il ne distribue pas les enfants dans l'espace mais les dessine séquentiellement les uns sur les autres. Si vous ne voulez pas que les éléments se chevauchent, utilisez un autre conteneur (LinearLayout, ConstraintLayout). Pour un chevauchement partiel avec contrôle de l'ordre de dessin, utilisez layout_gravity pour le décalage et elevation pour l'ordre Z.

Quel est le plus rapide : FrameLayout ou ConstraintLayout ?

FrameLayout est plus rapide pour les cas les plus simples — un élément enfant, sans positionnement complexe. FrameLayout exécute onMeasure en un temps minimal sans calculer de contraintes. Cependant, la différence n'est perceptible qu'à des centaines de répétitions (RecyclerView avec des dizaines de milliers d'éléments). Pour un écran typique (1 à 3 FrameLayouts), la différence est de l'ordre de la microseconde et n'affecte pas l'UX. ConstraintLayout est le choix universel pour 95 % des tâches.

Résumé

  • FrameLayout — la ViewGroup Android la plus simple pour la superposition d'éléments et les conteneurs placeholder avec une surcharge minimale.
  • Superposition de couches — chaque nouvel enfant se dessine sur le précédent ; le dernier déclaré en XML est le plus haut.
  • Premier plan — un drawable sur tous les enfants pour les effets de superposition, le masquage et les animations ripple.
  • measureAllChildren — la désactivation (false) exclut les éléments GONE du calcul de taille, accélérant le dessin de 20 à 60 %.
  • layout_gravity — le seul mécanisme de positionnement : top, bottom, left, right, center et leurs combinaisons.
  • Conteneur de Fragment — le cas d'utilisation le plus courant : FrameLayout (ou FragmentContainerView) pour FragmentTransaction.replace().
  • Performances — le conteneur le plus rapide pour 1 enfant ; pour les layouts complexes, il est dépassé par ConstraintLayout.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi