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 решава је угнежђивање изгледа. Сваки угнежђени 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 налазе на истом нивоу угнежђивања. Уместо да се елемент А смести у LinearLayout, а LinearLayout у RelativeLayout, сви елементи се директно везују за родитељски ConstraintLayout или један за другог преко атрибута. Ово даје: мању потрошњу меморије (сваки ViewGroup је објекат у Java heap-у), убрзање layout passa (мање рекурзивних позива), предвидљивије понашање при промени величине екрана.

Систем констрејната: везивања, bias и маргине

Констрејнт — је веза између ивице једног View-а (или његовог центра) и ивице другог View-а или родитеља. Сваки View може имати до 8 констрејната: леви, горњи, десни, доњи, start, end, baseline и центар. Минимално за позиционирање су довољна два окомита констрејнта (нпр. горњи + леви).

Формат атрибута: app:layout_constraint[Извор]_to[Циљ]Of="[id]" — где је Извор везана ивица (Left, Right, Top, Bottom, Start, End, Baseline), Циљ је ивица циља. Пример: 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. Маргина се задаје стандардним android:layout_margin*, али констрејнт и маргина раде независно: маргина је растојање од констрејнта, а не од суседног View-а.

Процентуално позиционирање

Од ConstraintLayout 1.1+ доступна је подршка за процентуалне величине преко layout_constraintWidth_percent и layout_constraintHeight_percent. Вредност 0.3 значи 30% ширине/висине родитеља. У комбинацији са bias-ом, ово омогућава креирање адаптивних изгледа без програмирања.

Chains и Guidelines: ланци и водичи

Chain (ланац) — је група од два или више View-а повезаних двосмерним констрејнтима (A везан за B, B за A). Ланци аутоматски распоређују простор између елемената у једном од режима: spread (равномерно, са уважавањем маргина), 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 за сваки елемент појединачно, довољно је променити видљивост једне Group. Group не утиче на позиционирање — само на видљивост. Flow — виртуелни помоћник за креирање „течних" изгледа: елементи се аутоматски пребацују у нови ред/колону када нема места, као текст у пасусу. Flow подржава wrapMode: none, chain и aligned.

Ови алати (Barrier, Group, Flow, Guideline) називају се виртуелним помоћницима јер нису View-ови у класичном смислу — не заузимају место у хијерархији и не учествују у фокусу или додирним догађајима. Њихов циљ је да поједноставе одржавање сложених изгледа без додавања угнежђених контејнера.

Примери: XML и Kotlin

Пример 1: Основна форма са констрејнтима

Једноставна форма за пријаву са пољем за е-пошту, лозинком и дугметом. Сви елементи су везани за parent, осим дугмета — оно је испод поља за лозинку. Користи се равна хијерархија — сва три елемента на истом нивоу.

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 констрејнта са уважавањем хоризонталне маргине. Ово је аналог 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%. Леви елемент је везан за леву ивицу parent и десном ивицом за guideline; десни — левом ивицом за guideline и за десну ивицу 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-а израчунава из констрејната: ако су задати леви и десни констрејнти са маргином, ширина = 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, али пружа Compose верзију ConstraintLayout-а (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), изаберите покренуту апликацију и пређите курсором преко проблематичног елемента. Видећете све констрејнте, маргине, 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. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође