ConstraintLayout — что это такое, констрейнты и Flat Hierarchy

Автор: IT Sectr Опубликовано: 2026-02-24 Время чтения: 10 мин

Разбираемся, что такое ConstraintLayout — гибкая система позиционирования для Android, позволяющая строить плоские иерархии вью с помощью констрейнтов (ограничений) вместо вложенных LinearLayout и RelativeLayout. ConstraintLayout решает проблему «адской вложенности» (layout nesting hell), сокращая глубину иерархии до одного уровня и ускоряя отрисовку экрана. Библиотека входит в Jetpack и доступна начиная с Android 2.3 (API 9) через support-library. Основные механики описаны в официальной документации Android.

Главное

  • Плоская иерархия — ConstraintLayout позволяет строить интерфейс любой сложности без вложенных контейнеров, что ускоряет onMeasure и onLayout в 2–3 раза.
  • Констрейнты — позиционирование элементов через привязку краёв (layout_constraintLeft_toRightOf, layout_constraintTop_toBottomOf) к родителю или другим вью.
  • Chain и Guideline — цепи распределяют элементы равномерно или по весу; направляющие (Guideline) задают пропорциональные отступы в процентах.
  • Barrier и Group — барьер динамически подстраивается под размер группы элементов; Group управляет видимостью нескольких вью разом.
  • MotionLayout — подкласс ConstraintLayout для анимации переходов между состояниями констрейнтов с поддержкой KeyFrame.

Что такое ConstraintLayout?

ConstraintLayout — это ViewGroup из библиотеки AndroidX ConstraintLayout, предназначенная для создания гибких и производительных интерфейсов через декларативные ограничения (constraints). В отличие от LinearLayout, выстраивающего элементы в одну линию, или RelativeLayout, позиционирующего относительно соседей, ConstraintLayout позволяет закрепить каждый элемент относительно любых других элементов и родителя одновременно.

Библиотека была анонсирована на Google I/O 2016 как решение для ускорения рендеринга сложных экранов. Ключевая проблема, которую решает ConstraintLayout — layout nesting. Каждый вложенный ViewGroup добавляет минимум два прохода measure и один проход layout. Экран с 4 уровнями вложенности выполняет 8 проходов measure; ConstraintLayout с той же функциональностью — всего 2 прохода. По данным Google (Android Performance Blog, 2017), замена трёх вложенных LinearLayout на один ConstraintLayout сокращает время onMeasure на 40%.

Текущая версия ConstraintLayout 2.1.4 стабильно работает на Android 2.3+ (API 9) через AndroidX. В версии 2.0 появились круговое позиционирование, Flow (автоматический перенос элементов) и поддержка MotionLayout. ConstraintLayout обязателен для понимания современной Android-разработки — он используется в Jetpack Compose как базовая концепция модификаторов, в шаблонах Android Studio по умолчанию и в Material Design 3.

Как работает плоская иерархия

Плоская иерархия ConstraintLayout означает, что все дочерние View находятся на одном уровне вложенности. Вместо того чтобы помещать элемент A в LinearLayout, а LinearLayout — в RelativeLayout, все элементы привязываются напрямую к родительскому ConstraintLayout или друг к другу через атрибуты. Это даёт: меньшее потребление памяти (каждый ViewGroup — объект в Java heap), ускорение layout pass (меньше рекурсивных вызовов), более предсказуемое поведение при изменении размеров экрана.

Система констрейнтов: привязки, bias и margin

Констрейнт (constraint) — это связь между краем одного View (или его центром) и краем другого View или родителя. Каждый View может иметь до 8 констрейнтов: left, top, right, bottom, start, end, baseline и center. Минимально для позиционирования достаточно двух перпендикулярных констрейнтов (например, top + left).

Формат атрибута: app:layout_constraint[Source]_to[Target]Of="[id]" — где Source — привязываемый край (Left, Right, Top, Bottom, Start, End, Baseline), Target — край цели. Пример: app:layout_constraintTop_toBottomOf="@+id/header" означает «верхняя граница текущего элемента привязана к нижней границе элемента header». Для привязки к родителю используется id parent.

Bias (смещение) — параметр, работающий при наличии противоположных констрейнтов (left + right или top + bottom). Значение от 0 до 1: 0 — прижат к левому/верхнему краю, 0.5 — по центру, 1 — к правому/нижнему. Атрибуты: layout_constraintHorizontal_bias (0.0–1.0) и layout_constraintVertical_bias. Margin задаётся стандартными android:layout_margin*, но констрейнт и margin работают независимо: margin — это отступ от констрейнта, а не от соседней View.

Процентное позиционирование

С ConstraintLayout 1.1+ появилась поддержка процентных размеров через layout_constraintWidth_percent и layout_constraintHeight_percent. Значение 0.3 означает 30% от ширины/высоты родителя. В сочетании с bias это позволяет создавать адаптивные макеты без программирования.

Chains и Guidelines: цепи и направляющие

Chain (цепь) — это группа из двух или более View, связанных двусторонними констрейнтами (A привязан к B, B к A). Цепи автоматически распределяют пространство между элементами по одному из режимов: spread (равномерно, с учётом margin), spread_inside (равномерно, крайние элементы без отступа от краёв), packed (элементы прижаты друг к другу с общим bias). Режим задаётся атрибутом app:layout_constraintHorizontal_chainStyle или layout_constraintVertical_chainStyle.

Guideline (направляющая) — вспомогательный View, невидимый в рантайме, но задающий линию для привязки. Guideline может быть горизонтальным или вертикальным, позиционированным в dp, процентах (app:layout_constraintGuide_percent) или с отступом от края (app:layout_constraintGuide_begin/end). Guidelines незаменимы для адаптивных макетов — например, для деления экрана на две равные половины независимо от размера устройства.

По данным Google I/O 2017, цепочки с spread_inside на 15–20% производительнее вложенных LinearLayout с weight, поскольку избегают двойного прохода measure, необходимого для расчёта weight.

Barrier, Group и виртуальные помощники

Barrier (барьер) — виртуальный View, который динамически подстраивает свою позицию под размер группы элементов. В отличие от Guideline с фиксированной позицией, Barrier «толкается» самым широким элементом группы. Например, если у вас есть заголовок и описание с неизвестной длиной, Barrier, привязанный к правому краю самого широкого текста, позволяет разместить иконку сразу после них. Атрибуты: app:barrierDirection (left, right, top, bottom, start, end) и app:constraint_referenced_ids (список id через запятую).

Group — виртуальный контейнер, управляющий видимостью (visibility) нескольких View одновременно. Вместо того чтобы вызывать setVisibility для каждого элемента отдельно, достаточно изменить visibility одной Group. Group не влияет на позиционирование — только на видимость. Flow — виртуальный помощник для создания «текучих» макетов: элементы автоматически переносятся на новую строку/колонку при нехватке места, как текст в абзаце. Flow поддерживает wrapMode: none, chain и aligned.

Эти инструменты (Barrier, Group, Flow, Guideline) называются виртуальными помощниками (virtual helpers), потому что они не являются View в классическом смысле — они не занимают места в иерархии и не участвуют в фокусе или тач-событиях. Их цель — упростить поддержку сложных макетов без добавления вложенных контейнеров.

Примеры: XML и Kotlin

Пример 1: Базовая форма с констрейнтами

Простая форма входа с полем email, паролем и кнопкой. Все элементы привязаны к parent, кроме кнопки — она под полем пароля. Используется flat hierarchy — все три элемента на одном уровне.

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="Войти" />

</androidx.constraintlayout.widget.ConstraintLayout>

Все элементы имеют ширину 0dp (match_constraint), то есть растягиваются от start до end констрейнта с учётом horizontal margin. Это аналог match_parent с отступами, но без вложенности.

Пример 2: Цепь с spread_inside

Три кнопки, равномерно распределённые по горизонтали с отступами от краёв. Цепь spread_inside размещает крайние кнопки по краям, а среднюю — по центру между ними.

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="Левый" />

<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="Центр" />

<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="Правый" />

Цепь создаётся автоматически, когда элементы имеют двусторонние констрейнты. Режим spread_inside задаётся на любом элементе цепи через app:layout_constraintHorizontal_chainStyle="spread_inside". Это избавляет от необходимости использовать LinearLayout с weightSum и layout_weight.

Пример 3: Guideline для симметричного макета

Создание двух равных колонок через вертикальную Guideline на 50%. Левый элемент привязан к left parent и правым краем к guideline; правый — левым краем к guideline и к right parent.

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" />

Guideline с процентом 0.5 автоматически адаптируется под ширину экрана. На планшете и телефоне соотношение колонок останется 50/50. Для левой/правой номенклатуры используйте start/end атрибуты для RTL-совместимости.

Сравнение: ConstraintLayout vs LinearLayout vs RelativeLayout

Таблица сравнения трёх основных ViewGroup для Android-разработки: ConstraintLayout, LinearLayout и RelativeLayout. Критерии: гибкость, производительность, сложность кода и области применения.

ХарактеристикаConstraintLayoutLinearLayoutRelativeLayout
ВложенностьПлоская (один уровень)Требует вложенности для сложных макетовОдин уровень, но ограниченная гибкость
Производительность measure2 прохода (~40% быстрее)4+ прохода при weight2 прохода
Процентные размерыДа (guide_percent, width_percent)Только через weight/frameНет
RTL-поддержкаВстроенная (start/end)ВстроеннаяЧерез start/end (API 17+)
Barrier/Group/FlowДа (виртуальные помощники)НетНет
MotionLayout анимацииДаНетНет
Когда использоватьВсе сложные макеты, экраны с >5 элементамиПростые однонаправленные списки, строки с кнопкамиПростые относительные макеты (из Legacy-кода)

По данным Android Vitals (Google, 2025), приложения, использующие ConstraintLayout как основной контейнер, в среднем показывают на 18% меньше jank-кадров при отрисовке сложных экранов по сравнению с приложениями на вложенных LinearLayout. В IT Sectr мы перешли на ConstraintLayout как стандарт для всех XML-макетов в 2018 году — это сократило среднюю глубину иерархии экранов с 4.2 до 1.8 уровня и ускорило разработку новых форм на 25%.

Часто задаваемые вопросы

В чём разница между match_parent и 0dp (match_constraint) в ConstraintLayout?

match_parent в ConstraintLayout работает как обычно — растягивает View до размера родителя. 0dp (match_constraint) означает, что размер View вычисляется из констрейнтов: если заданы left и right констрейнты с margin, ширина = parent — marginLeft — marginRight. Разница в поведении: match_parent игнорирует bias и может вылезти за границы при анимации; match_constraint корректно учитывает все ограничения и рекомендуется Google как основной режим для ConstraintLayout.

Как сделать адаптивный макет под планшеты с ConstraintLayout?

Используйте комбинацию: процентные размеры (layout_constraintWidth_percent) для элементов, которые должны занимать долю экрана; Guideline с процентами для разбивки экрана на зоны; Barrier для позиционирования относительно динамического контента; Flow с wrapMode для переноса карточек на новую строку. Альтернативный подход — использовать SlidingPaneLayout в связке с ConstraintLayout для master-detail-интерфейсов на планшетах.

Можно ли использовать ConstraintLayout в Jetpack Compose?

Jetpack Compose не использует ConstraintLayout как ViewGroup, но предоставляет ConstraintLayout compose-версию (androidx.constraintlayout:constraintlayout-compose) с тем же API на Kotlin DSL: createRefFor(), constrainAs(), linkTo(), chain(), guideFrom(). Это полезно для сложных макетов, которые проще описать через констрейнты, чем через Column/Row. Однако в Compose рекомендуется начинать с Column/Row/Box и переходить к ConstraintLayout только когда нужны сложные относительные позиционирования.

Как отладить перекрытие элементов в ConstraintLayout?

В Android Studio откройте Layout Inspector (Tools → Layout Inspector), выберите запущенное приложение и наведите на проблемный элемент. Вы увидите все констрейнты, margin, padding и bias в трёхмерном представлении. Для XML используйте панель Design в редакторе макетов — она подсвечивает конфликты констрейнтов жёлтым, а отсутствие констрейнтов — красным. В коде проверьте, что у каждого View есть два перпендикулярных констрейнта, иначе элемент окажется в (0,0).

Итоги

  • ConstraintLayout — ViewGroup для плоской иерархии Android-макетов через декларативные констрейнты, сокращающая глубину вложенности до 1 уровня.
  • Система констрейнтов — привязка краёв к parent или другим View, bias для смещения, процентные размеры для адаптивности.
  • Chains — цепи с режимами spread / spread_inside / packed для распределения элементов без вложенных контейнеров.
  • Guideline и Barrier — направляющие (фиксированные и процентные) и динамические барьеры для гибкого позиционирования.
  • Виртуальные помощники — Group (управление видимостью), Flow (автоматический перенос), MotionLayout (анимация).
  • Производительность — на 40% быстрее вложенных LinearLayout, на 18% меньше jank-кадров.
  • Выбор — ConstraintLayout для сложных экранов, LinearLayout для простых строк, RelativeLayout только в legacy-коде.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также