Biz ConstraintLayout-un nə olduğunu izah edirik — Android üçün çevik yerləşdirmə sistemi, LinearLayout və RelativeLayout-lərin iç-içə yerləşdirilməsi əvəzinə constraintlər (məhdudiyyətlər) vasitəsilə düz iyerarxiyalar qurmağa imkan verir. ConstraintLayout layoutların iç-içə yerləşməsi problemini (layout nesting hell) həll edir, iyerarxiya dərinliyini bir səviyyəyə endirir və ekranın göstərilməsini sürətləndirir. Kitabxana Jetpack-ə daxildir və Android 2.3-dən (API 9) etibarən support-library vasitəsilə mövcuddur. Əsas mexanizmlər Android-in rəsmi sənədlərində təsvir edilmişdir.
Əsas məqamlar
ConstraintLayout — AndroidX ConstraintLayout kitabxanasından olan ViewGroup, deklarativ məhdudiyyətlər (constraints) vasitəsilə çevik və məhsuldar interfeyslər yaratmaq üçün nəzərdə tutulub. Elementləri bir xəttə düzən LinearLayout və ya qonşulara nisbətən yerləşdirən RelativeLayout-dan fərqli olaraq, ConstraintLayout hər elementi eyni anda hər hansı digər elementlərə və valideynə nisbətən bağlamağa imkan verir.
Kitabxana Google I/O 2016-da mürəkkəb ekranların renderini sürətləndirmək üçün həll yolu kimi təqdim edilmişdir. ConstraintLayout-un həll etdiyi əsas problem layoutların iç-içə yerləşməsidir. Hər iç-içə ViewGroup ən azı iki measure keçidi və bir layout keçidi əlavə edir. 4 səviyyəli iç-içə olan ekran 8 measure keçidi yerinə yetirir; eyni funksionallığa malik ConstraintLayout — cəmi 2 keçid. Google məlumatlarına görə (Android Performance Blog, 2017), üç iç-içə LinearLayout-u bir ConstraintLayout ilə əvəz etmək onMeasure vaxtını 40% azaldır.
Cari versiya ConstraintLayout 2.1.4 Android 2.3+ (API 9) ilə AndroidX vasitəsilə sabit işləyir. 2.0 versiyasında dairəvi yerləşdirmə, Flow (elementlərin avtomatik daşınması) və MotionLayout dəstəyi əlavə edilmişdir. ConstraintLayout müasir Android inkişafı üçün məcburidir — o, Jetpack Compose-da modifierlərin əsas konsepsiyası kimi, Android Studio-nun standart şablonlarında və Material Design 3-də istifadə olunur.
ConstraintLayout-un düz iyerarxiyası o deməkdir ki, bütün uşaq View-lər eyni iç-içə səviyyəsində yerləşir. A elementini LinearLayout-a, LinearLayout-u isə RelativeLayout-a yerləşdirmək əvəzinə, bütün elementlər birbaşa valideyn ConstraintLayout-a və ya bir-birinə atributlar vasitəsilə bağlanır. Bu, aşağıdakıları təmin edir: az yaddaş sərfiyyatı (hər ViewGroup Java heap-də bir obyektdir), layout keçidinin sürətlənməsi (daha az rekursiv çağırış), ekran ölçüsü dəyişikliklərində daha proqnozlaşdırıla bilən davranış.
Constraint (məhdudiyyət) — bir View-in kənarı (və ya mərkəzi) ilə başqa View-in və ya valideynin kənarı arasında əlaqədir. Hər View 8-ə qədər constraintə malik ola bilər: sol, yuxarı, sağ, aşağı, start, end, baseline və mərkəz. Yerləşdirmə üçün minimum iki perpendikulyar constraint kifayətdir (məsələn, yuxarı + sol).
Atribut formatı: app:layout_constraint[Mənbə]_to[Hədəf]Of="[id]" — burada Mənbə bağlanan kənar (Left, Right, Top, Bottom, Start, End, Baseline), Hədəf isə hədəfin kənarıdır. Nümunə: app:layout_constraintTop_toBottomOf="@+id/header" — «cari elementin yuxarı sərhəddi header elementinin aşağı sərhəddinə bağlanıb». Valideynə bağlamaq üçün parent id-si istifadə olunur.
Bias (sürüşmə) — əks constrainlər (left + right və ya top + bottom) olduqda işləyən parametr. Qiymət 0-dan 1-ə qədər: 0 — sol/yuxarı kənara sıxılıb, 0.5 — mərkəzdə, 1 — sağ/aşağı kənarda. Parametrlər: layout_constraintHorizontal_bias (0.0–1.0) və layout_constraintVertical_bias. Margin standart android:layout_margin* ilə təyin edilir, lakin constraint və margin müstəqil işləyir: margin constraint-dən olan məsafədir, qonşu View-dən yox.
ConstraintLayout 1.1+-dan etibarən layout_constraintWidth_percent və layout_constraintHeight_percent vasitəsilə faiz ölçüləri dəstəklənir. 0.3 dəyəri valideynin eninin/hündürlüyünün 30%-i deməkdir. Bias ilə birlikdə bu, proqramlaşdırma olmadan adaptiv layoutlar yaratmağa imkan verir.
Chain (zəncir) — ikitərəfli constrainlərlə bağlanmış iki və ya daha çox View qrupudur (A B-yə, B A-ya bağlanıb). Zəncirlər elementlər arasında məkanı aşağıdakı rejimlərdən birinə uyğun avtomatik paylayır: spread (margin nəzərə alınmaqla bərabər), spread_inside (bərabər, kənar elementlər kənarlardan boşluqsuz), packed (elementlər ümumi bias ilə bir-birinə sıxılıb). Rejim app:layout_constraintHorizontal_chainStyle və ya layout_constraintVertical_chainStyle atributu ilə təyin edilir.
Guideline (bələdçi xətti) — icra zamanı görünməyən, lakin bağlama xətti təyin edən köməkçi View. Guideline üfüqi və ya şaquli ola bilər, dp, faiz (app:layout_constraintGuide_percent) və ya kənardan məsafə ilə (app:layout_constraintGuide_begin/end) yerləşdirilir. Guidelines adaptiv layoutlar üçün əvəzolunmazdır — məsələn, cihaz ölçüsündən asılı olmayaraq ekranı iki bərabər yarıya bölmək üçün.
Google I/O 2017 məlumatlarına görə, spread_inside zəncirləri weight ilə iç-içə LinearLayout-dan 15–20% daha məhsuldardır, çünki weight hesablanması üçün lazım olan ikiqat measure keçidindən qaçır.
Barrier (baryer) — dinamik olaraq öz mövqeyini element qrupunun ölçüsünə uyğunlaşdıran virtual View. Sabit mövqeli Guideline-dan fərqli olaraq, Barrier qrupun ən geniş elementi tərəfindən «itələnir». Məsələn, naməlum uzunluqda başlıq və təsviriniz varsa, ən geniş mətnin sağ kənarına bağlanmış Barrier ikonadanı dərhal onların yanında yerləşdirməyə imkan verir. Parametrlər: app:barrierDirection (left, right, top, bottom, start, end) və app:constraint_referenced_ids (vergüllə ayrılmış id siyahısı).
Group — eyni anda bir neçə View-in görünməsini idarə edən virtual konteyner. Hər element üçün ayrıca setVisibility çağırmaq əvəzinə, bir Group-un görünməsini dəyişmək kifayətdir. Group yerləşdirməyə təsir etmir — yalnız görünməyə. Flow — «axıcı» layoutlar yaratmaq üçün virtual köməkçi: yer çatışmazlığı olduqda elementlər avtomatik olaraq yeni sətir/sütuna keçir, mətndəki kimi. Flow wrapMode: none, chain və aligned rejimlərini dəstəkləyir.
Bu alətlər (Barrier, Group, Flow, Guideline) virtual köməkçilər adlanır, çünki onlar klassik mənada View deyillər — iyerarxiyada yer tutmur və fokus və ya toxunma hadisələrində iştirak etmirlər. Onların məqsədi iç-içə konteynerlər əlavə etmədən mürəkkəb layoutların saxlanmasını asanlaşdırmaqdır.
Email sahəsi, şifrə və düymə ilə sadə giriş forması. Düymədən başqa bütün elementlər parent-ə bağlanıb — o şifrə sahəsinin altında yerləşir. Düz iyerarxiya istifadə olunur — hər üç element eyni səviyyədə.
<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="Daxil ol" />
</androidx.constraintlayout.widget.ConstraintLayout>
Bütün elementlərin eni 0dp (match_constraint)-dir, yəni üfüqi margin nəzərə alınmaqla start-dan end-ə qədər uzanır. Bu, margin ilə match_parent-ın analoqudur, lakin iç-içə olmadan.
Üç düymə, kənarlardan boşluqlarla üfüqi olaraq bərabər paylanmışdır. spread_inside zənciri kənar düymələri kənarlara, ortadakını isə onların arasında mərkəzə yerləşdirir.
<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="Sol" />
<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="Mərkəz" />
<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="Sağ" />
Zəncir elementlər ikitərəfli constraintlərə malik olduqda avtomatik yaranır. spread_inside rejimi zəncirin istənilən elementində app:layout_constraintHorizontal_chainStyle="spread_inside" vasitəsilə təyin edilir. Bu, weightSum və layout_weight ilə LinearLayout istifadə etməyə ehtiyacı aradan qaldırır.
50%-də şaquli Guideline vasitəsilə iki bərabər sütun yaratmaq. Sol element sol parent kənarına və sağ kənarı ilə guideline-ə bağlanıb; sağ element — sol kənarı ilə guideline-ə və sağ parent kənarına.
<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" />
0.5 faizli Guideline avtomatik olaraq ekranın eninə uyğunlaşır. Planşet və telefonda sütun nisbətləri 50/50 qalacaq. Sol/sağ nomenklaturası üçün RTL uyğunluğu üçün start/end atributlarından istifadə edin.
Android inkişafı üçün üç əsas ViewGroup-un müqayisə cədvəli: ConstraintLayout, LinearLayout və RelativeLayout. Meyarlar: çeviklik, məhsuldarlıq, kod mürəkkəbliyi və tətbiq sahələri.
| Xüsusiyyət | ConstraintLayout | LinearLayout | RelativeLayout |
|---|---|---|---|
| İç-içə yerləşmə | Düz (bir səviyyə) | Mürəkkəb layoutlar üçün iç-içə tələb edir | Bir səviyyə, lakin məhdud çeviklik |
| Measure performansı | 2 keçid (~40% daha sürətli) | Weight ilə 4+ keçid | 2 keçid |
| Faiz ölçüləri | Bəli (guide_percent, width_percent) | Yalnız weight/frame ilə | Xeyr |
| RTL dəstəyi | Daxili (start/end) | Daxili | start/end ilə (API 17+) |
| Barrier/Group/Flow | Bəli (virtual köməkçilər) | Xeyr | Xeyr |
| MotionLayout animasiyaları | Bəli | Xeyr | Xeyr |
| Nə vaxt istifadə edilməli | Bütün mürəkkəb layoutlar, >5 elementli ekranlar | Sadə biristiqamətli siyahılar, düymə sətirləri | Sadə nisbi layoutlar (Legacy koddan) |
Android Vitals məlumatlarına görə (Google, 2025), ConstraintLayout-u əsas konteyner kimi istifadə edən tətbiqlər, iç-içə LinearLayout-larda olan tətbiqlərlə müqayisədə mürəkkəb ekranların renderində orta hesabla 18% daha az jank-frame göstərir. IT Sectr-da 2018-ci ildə bütün XML layoutlar üçün ConstraintLayout-u standart olaraq qəbul etdik — bu, ekran iyerarxiyasının orta dərinliyini 4.2-dən 1.8 səviyyəsinə endirdi və yeni formaların inkişafını 25% sürətləndirdi.
Tez-tez verilən suallar
match_parent ConstraintLayout-da adi qaydada işləyir — View-i valideynin ölçüsünə qədər uzadır. 0dp (match_constraint) o deməkdir ki, View-in ölçüsü constrainlərdən hesablanır: sol və sağ constrainlər margin ilə təyin edilibsə, en = parent — marginLeft — marginRight. Davranış fərqi: match_parent bias-ı nəzərə almır və animasiya zamanı sərhədləri aşa bilər; match_constraint bütün məhdudiyyətləri düzgün nəzərə alır və Google tərəfindən ConstraintLayout üçün əsas rejim kimi tövsiyə olunur.
Kombinasiyadan istifadə edin: ekranın payını tutmalı elementlər üçün faiz ölçüləri (layout_constraintWidth_percent); ekranı zonalara bölmək üçün faizli Guideline; dinamik məzmuna nisbətən yerləşdirmə üçün Barrier; kartları yeni sətirə keçirmək üçün wrapMode ilə Flow. Alternativ yanaşma — planşetlərdə master-detail interfeysləri üçün ConstraintLayout ilə birlikdə SlidingPaneLayout istifadə etməkdir.
Jetpack Compose ConstraintLayout-u ViewGroup kimi istifadə etmir, lakin Kotlin DSL-də eyni API ilə ConstraintLayout-un Compose versiyasını (androidx.constraintlayout:constraintlayout-compose) təqdim edir: createRefFor(), constrainAs(), linkTo(), chain(), guideFrom(). Bu, Column/Row ilə təsvir etməkdən daha asan olan mürəkkəb layoutlar üçün faydalıdır. Bununla belə, Compose-da Column/Row/Box ilə başlamaq və yalnız mürəkkəb nisbi yerləşdirmələr lazım olduqda ConstraintLayout-a keçmək tövsiyə olunur.
Android Studio-da Layout Inspector-u açın (Tools → Layout Inspector), işləyən tətbiqi seçin və problemli elementin üzərinə gəlin. Bütün constrainləri, margin, padding və bias-ı üçölçülü görünüşdə görəcəksiniz. XML üçün layout redaktorunda Design panelindən istifadə edin — o, constraint konfliktlərini sarı, constraint olmamasını isə qırmızı rənglə vurğulayır. Kodda hər View-in iki perpendikulyar constraint-ə malik olduğunu yoxlayın, əks halda element (0,0) koordinatlarında olacaq.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun