ConstraintLayout — qu'est-ce que c'est, contraintes et hiérarchie plate

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

Découvrons ce qu'est ConstraintLayout — un système de positionnement flexible pour Android permettant de construire des hiérarchies plates de vues avec des contraintes au lieu de LinearLayout et RelativeLayout imbriqués. ConstraintLayout résout le problème de « l'imbrication infernale » (layout nesting hell) en réduisant la profondeur de la hiérarchie à un seul niveau et en accélérant le rendu de l'écran. La bibliothèque fait partie de Jetpack et est disponible à partir d'Android 2.3 (API 9) via la support-library. Les principaux mécanismes sont décrits dans la documentation officielle d'Android.

Points clés

  • Hiérarchie plate — ConstraintLayout permet de construire des interfaces de toute complexité sans conteneurs imbriqués, accélérant onMeasure et onLayout de 2 à 3 fois.
  • Contraintes — positionnement des éléments par liaison des bords (layout_constraintLeft_toRightOf, layout_constraintTop_toBottomOf) au parent ou à d'autres vues.
  • Chaîne et Guideline — les chaînes distribuent les éléments uniformément ou par poids ; les guides définissent des marges proportionnelles en pourcentages.
  • Barrier et Group — la barrière s'adapte dynamiquement à la taille d'un groupe d'éléments ; Group gère la visibilité de plusieurs vues à la fois.
  • MotionLayout — une sous-classe de ConstraintLayout pour animer les transitions entre les états de contraintes avec prise en charge de KeyFrame.

Qu'est-ce que ConstraintLayout ?

ConstraintLayout est un ViewGroup de la bibliothèque AndroidX ConstraintLayout, conçu pour créer des interfaces flexibles et performantes grâce à des contraintes déclaratives. Contrairement à LinearLayout qui aligne les éléments sur une ligne, ou à RelativeLayout qui positionne les éléments par rapport aux voisins, ConstraintLayout permet d'ancrer chaque élément par rapport à n'importe quel autre élément et au parent simultanément.

La bibliothèque a été annoncée à Google I/O 2016 comme une solution pour accélérer le rendu des écrans complexes. Le problème clé que résout ConstraintLayout est l'imbrication des layouts. Chaque ViewGroup imbriqué ajoute au moins deux passes de measure et une passe de layout. Un écran avec 4 niveaux d'imbrication effectue 8 passes de measure ; ConstraintLayout avec la même fonctionnalité n'effectue que 2 passes. Selon Google (Android Performance Blog, 2017), remplacer trois LinearLayouts imbriqués par un seul ConstraintLayout réduit le temps de onMeasure de 40 %.

La version actuelle ConstraintLayout 2.1.4 fonctionne stablement sur Android 2.3+ (API 9) via AndroidX. La version 2.0 a introduit le positionnement circulaire, Flow (enroulement automatique des éléments) et la prise en charge de MotionLayout. ConstraintLayout est essentiel pour comprendre le développement Android moderne — il est utilisé dans Jetpack Compose comme concept de base des modificateurs, dans les modèles par défaut d'Android Studio et dans Material Design 3.

Comment fonctionne la hiérarchie plate

La hiérarchie plate de ConstraintLayout signifie que toutes les vues enfants sont au même niveau d'imbrication. Au lieu de placer l'élément A dans un LinearLayout, et le LinearLayout dans un RelativeLayout, tous les éléments sont liés directement au ConstraintLayout parent ou les uns aux autres via des attributs. Cela offre : une consommation mémoire réduite (chaque ViewGroup est un objet dans le heap Java), une passe de layout plus rapide (moins d'appels récursifs) et un comportement plus prévisible lors des changements de taille d'écran.

Système de contraintes : liaisons, bias et marge

Une contrainte est une connexion entre le bord d'une vue (ou son centre) et le bord d'une autre vue ou du parent. Chaque vue peut avoir jusqu'à 8 contraintes : left, top, right, bottom, start, end, baseline et center. Au minimum, deux contraintes perpendiculaires suffisent pour le positionnement (par exemple, top + left).

Format de l'attribut : app:layout_constraint[Source]_to[Target]Of="[id]" — où Source est le bord lié (Left, Right, Top, Bottom, Start, End, Baseline) et Target est le bord cible. Exemple : app:layout_constraintTop_toBottomOf="@+id/header" signifie « le bord supérieur de l'élément actuel est lié au bord inférieur de l'élément header ». Pour lier au parent, l'id parent est utilisé.

Le bias (biais) est un paramètre qui fonctionne lorsque des contraintes opposées sont présentes (left + right ou top + bottom). Les valeurs vont de 0 à 1 : 0 — plaqué contre le bord gauche/supérieur, 0.5 — centré, 1 — contre le bord droit/inférieur. Attributs : layout_constraintHorizontal_bias (0.0–1.0) et layout_constraintVertical_bias. Les marges sont définies avec les standards android:layout_margin*, mais les contraintes et les marges fonctionnent indépendamment : la marge est un décalage par rapport à la contrainte, et non par rapport à la vue voisine.

Positionnement en pourcentage

À partir de ConstraintLayout 1.1+, la prise en charge des tailles en pourcentage a été ajoutée via layout_constraintWidth_percent et layout_constraintHeight_percent. Une valeur de 0.3 signifie 30 % de la largeur/hauteur du parent. Combiné avec le bias, cela permet de créer des mises en page adaptatives sans programmation.

Chaînes et Guidelines

Une chaîne (Chain) est un groupe de deux vues ou plus connectées par des contraintes bidirectionnelles (A est lié à B, B est lié à A). Les chaînes distribuent automatiquement l'espace entre les éléments selon l'un des modes : spread (uniformément, en tenant compte des marges), spread_inside (uniformément, éléments extérieurs sans marge de bord), packed (éléments serrés avec un bias commun). Le mode est défini via l'attribut app:layout_constraintHorizontal_chainStyle ou layout_constraintVertical_chainStyle.

Une Guideline (guide) est une vue auxiliaire, invisible à l'exécution, qui définit une ligne pour la liaison. Une Guideline peut être horizontale ou verticale, positionnée en dp, en pourcentages (app:layout_constraintGuide_percent) ou avec un décalage par rapport au bord (app:layout_constraintGuide_begin/end). Les Guidelines sont indispensables pour les mises en page adaptatives — par exemple, pour diviser l'écran en deux moitiés égales quelle que soit la taille de l'appareil.

Selon Google I/O 2017, les chaînes avec spread_inside sont 15 à 20 % plus performantes que les LinearLayouts imbriqués avec weight, car elles évitent la double passe de measure nécessaire au calcul du weight.

Barrier, Group et assistants virtuels

Une Barrier (barrière) est une vue virtuelle qui ajuste dynamiquement sa position en fonction de la taille d'un groupe d'éléments. Contrairement à une Guideline à position fixe, une Barrier est « poussée » par l'élément le plus large du groupe. Par exemple, si vous avez un titre et une description de longueurs inconnues, une Barrier liée au bord droit du texte le plus large permet de placer une icône juste après. Attributs : app:barrierDirection (left, right, top, bottom, start, end) et app:constraint_referenced_ids (liste d'ids séparés par des virgules).

Group est un conteneur virtuel qui gère la visibilité de plusieurs vues simultanément. Au lieu d'appeler setVisibility pour chaque élément individuellement, il suffit de modifier la visibilité d'un seul Group. Group n'affecte pas le positionnement — seulement la visibilité. Flow est un assistant virtuel pour créer des mises en page « fluides » : les éléments passent automatiquement à une nouvelle ligne/colonne lorsque l'espace manque, comme le texte dans un paragraphe. Flow prend en charge wrapMode : none, chain et aligned.

Ces outils (Barrier, Group, Flow, Guideline) sont appelés assistants virtuels car ils ne sont pas des vues au sens classique — ils ne prennent pas de place dans la hiérarchie et ne participent pas aux événements de focus ou tactiles. Leur objectif est de simplifier la maintenance de mises en page complexes sans ajouter de conteneurs imbriqués.

Exemples : XML et Kotlin

Exemple 1 : Formulaire de base avec contraintes

Un formulaire de connexion simple avec un champ email, un champ mot de passe et un bouton. Tous les éléments sont liés au parent, sauf le bouton — il se trouve sous le champ mot de passe. Une hiérarchie plate est utilisée — les trois éléments sont au même niveau.

xml
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/email_input"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="32dp"
        android:layout_marginHorizontal="16dp" />

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/password_input"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/email_input"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="16dp"
        android:layout_marginHorizontal="16dp" />

    <Button
        android:id="@+id/login_button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/password_input"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="24dp"
        android:layout_marginHorizontal="16dp"
        android:text="Se connecter" />

</androidx.constraintlayout.widget.ConstraintLayout>

Tous les éléments ont une largeur de 0dp (match_constraint), ce qui signifie qu'ils s'étendent de la contrainte start à end en tenant compte des marges horizontales. Cela équivaut à match_parent avec marges, mais sans imbrication.

Exemple 2 : Chaîne avec spread_inside

Trois boutons répartis uniformément horizontalement avec des marges de bord. La chaîne spread_inside place les boutons extérieurs aux bords et celui du milieu centré entre eux.

xml
<Button
    android:id="@+id/btn_left"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/btn_center"
    android:text="Gauche" />

<Button
    android:id="@+id/btn_center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@+id/btn_left"
    app:layout_constraintRight_toLeftOf="@+id/btn_right"
    android:text="Centre" />

<Button
    android:id="@+id/btn_right"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@+id/btn_center"
    app:layout_constraintRight_toRightOf="parent"
    android:text="Droite" />

La chaîne est créée automatiquement lorsque les éléments ont des contraintes bidirectionnelles. Le mode spread_inside est défini sur n'importe quel élément de la chaîne via app:layout_constraintHorizontal_chainStyle="spread_inside". Cela élimine le besoin d'un LinearLayout avec weightSum et layout_weight.

Exemple 3 : Guideline pour une mise en page symétrique

Création de deux colonnes égales à l'aide d'une Guideline verticale à 50 %. L'élément gauche est lié au parent gauche et son bord droit à la guideline ; l'élément droit est lié par son bord gauche à la guideline et au parent droit.

xml
<androidx.constraintlayout.widget.Guideline
    android:id="@+id/gl_midpoint"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.5" />

<TextView
    android:id="@+id/left_card"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/gl_midpoint"
    android:layout_margin="8dp"
    android:background="@color/card_background" />

<TextView
    android:id="@+id/right_card"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toRightOf="@+id/gl_midpoint"
    app:layout_constraintRight_toRightOf="parent"
    android:layout_margin="8dp"
    android:background="@color/card_background" />

Une Guideline avec un pourcentage de 0.5 s'adapte automatiquement à la largeur de l'écran. Sur tablette comme sur téléphone, le ratio des colonnes reste 50/50. Pour la nomenclature gauche/droite, utilisez les attributs start/end pour la compatibilité RTL.

Comparaison : ConstraintLayout vs LinearLayout vs RelativeLayout

Tableau comparatif des trois principaux ViewGroups pour le développement Android : ConstraintLayout, LinearLayout et RelativeLayout. Critères : flexibilité, performance, complexité du code et cas d'utilisation.

CaractéristiqueConstraintLayoutLinearLayoutRelativeLayout
ImbricationPlate (un niveau)Nécessite une imbrication pour les layouts complexesUn niveau, mais flexibilité limitée
Performance de measure2 passes (~40 % plus rapide)4+ passes avec weight2 passes
Tailles en pourcentageOui (guide_percent, width_percent)Uniquement via weight/frameNon
Support RTLIntégré (start/end)IntégréVia start/end (API 17+)
Barrier/Group/FlowOui (assistants virtuels)NonNon
Animations MotionLayoutOuiNonNon
Quand utiliserTous les layouts complexes, écrans avec >5 élémentsListes unidirectionnelles simples, lignes avec boutonsLayouts relatifs simples (code legacy)

Selon Android Vitals (Google, 2025), les applications utilisant ConstraintLayout comme conteneur principal présentent en moyenne 18 % de trames jank en moins lors du rendu d'écrans complexes par rapport aux applications utilisant des LinearLayouts imbriqués. Chez IT Sectr, nous sommes passés à ConstraintLayout comme standard pour tous les layouts XML en 2018 — cela a réduit la profondeur moyenne de la hiérarchie d'écran de 4,2 à 1,8 niveaux et accéléré le développement de nouveaux formulaires de 25 %.

Foire aux questions

Quelle est la différence entre match_parent et 0dp (match_constraint) dans ConstraintLayout ?

match_parent dans ConstraintLayout fonctionne comme d'habitude — il étire la vue à la taille du parent. 0dp (match_constraint) signifie que la taille de la vue est calculée à partir des contraintes : si les contraintes left et right avec marges sont définies, la largeur = parent — marginLeft — marginRight. La différence de comportement : match_parent ignore le bias et peut déborder pendant l'animation ; match_constraint respecte correctement toutes les contraintes et est recommandé par Google comme mode principal pour ConstraintLayout.

Comment créer une mise en page adaptative pour tablettes avec ConstraintLayout ?

Utilisez une combinaison de : tailles en pourcentage (layout_constraintWidth_percent) pour les éléments qui doivent occuper une partie de l'écran ; Guideline avec pourcentages pour diviser l'écran en zones ; Barrier pour le positionnement relatif au contenu dynamique ; Flow avec wrapMode pour le retour à la ligne des cartes. Une approche alternative consiste à utiliser SlidingPaneLayout en combinaison avec ConstraintLayout pour les interfaces master-detail sur tablettes.

Peut-on utiliser ConstraintLayout dans Jetpack Compose ?

Jetpack Compose n'utilise pas ConstraintLayout en tant que ViewGroup, mais fournit une version Compose de ConstraintLayout (androidx.constraintlayout:constraintlayout-compose) avec la même API en Kotlin DSL : createRefFor(), constrainAs(), linkTo(), chain(), guideFrom(). C'est utile pour les layouts complexes plus faciles à décrire via des contraintes qu'avec Column/Row. Cependant, dans Compose, il est recommandé de commencer par Column/Row/Box et de passer à ConstraintLayout uniquement lorsque des positionnements relatifs complexes sont nécessaires.

Comment déboguer le chevauchement d'éléments dans ConstraintLayout ?

Dans Android Studio, ouvrez Layout Inspector (Tools → Layout Inspector), sélectionnez l'application en cours d'exécution et survolez l'élément problématique. Vous verrez toutes les contraintes, marges, padding et bias dans une représentation 3D. Pour XML, utilisez le panneau Design dans l'éditeur de layout — il surligne les conflits de contraintes en jaune et les contraintes manquantes en rouge. Dans le code, assurez-vous que chaque vue a deux contraintes perpendiculaires, sinon l'élément se retrouvera à (0,0).

Résumé

  • ConstraintLayout — un ViewGroup pour les layouts Android à hiérarchie plate via des contraintes déclaratives, réduisant la profondeur d'imbrication à 1 niveau.
  • Système de contraintes — liaison des bords au parent ou à d'autres vues, bias pour le décalage, tailles en pourcentage pour l'adaptabilité.
  • Chaînes — chaînes avec modes spread / spread_inside / packed pour distribuer les éléments sans conteneurs imbriqués.
  • Guideline et Barrier — guides fixes et en pourcentage, et barrières dynamiques pour un positionnement flexible.
  • Assistants virtuels — Group (gestion de la visibilité), Flow (enroulement automatique), MotionLayout (animation).
  • Performance — 40 % plus rapide que les LinearLayouts imbriqués, 18 % de trames jank en moins.
  • Choix — ConstraintLayout pour les écrans complexes, LinearLayout pour les lignes simples, RelativeLayout uniquement dans le code legacy.

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