Розміри елементів у ConstraintLayout
У ConstraintLayout застосовуються три способи встановлення розмірів:
- Встановлення точних розмірів, наприклад,
123dp - Значення
WRAP_CONTENT, яке задає для віджета розміри, достатні для розташування його вмісту - Значення
0dp, яке еквівалентне значенню "MATCH_CONSTRAINT" у коді Java. У цьому разі розміри елемента встановлюються виходячи із зазначених для нього обмежень. За замовчуванням елемент займає весь доступний простір.
Застосуємо всі три типи встановлення розмірів:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="160dp"
android:layout_height="wrap_content"
android:text="Top TextView"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Center TextView"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bottom TextView"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Тут створюються три елементи TextView. Усі вони центруються по горизонталі, але по вертикалі розташовуються по верхній і нижній межі контейнера і в центрі. Для всіх трьох TextView для висоти задано значення wrap_content, тобто всі три елементи займатимуть ту висоту, яка для них є кращою, щоб вмістити вміст:
android:layout_height="wrap_content"
Однак для кожного елемента задано свої налаштування ширини. Для верхнього TextView встановлено точні розміри - 160 одиниць:
android:layout_width="160dp"
Для центрального TextView встановлено значення "0dp", завдяки чому елемент за замовчуванням займатиме весь доступний для нього простір (у цьому разі розтягуватиметься по горизонталі):
android:layout_width="0dp"
Для нижнього TextView встановлено значення "wrap_content", тобто елемент прийматиме ту ширину, яка необхідна для вміщення його вмісту:
android:layout_width="wrap_content"
Варто зазначити, що у вкладених віджетах у ConstraintLayout не рекомендується використовувати значення match_parent, яке дає змогу віджету зайняти весь доступний простір. Замість цього рекомендується використовувати 0dp або "MATCH_CONSTRAINT" - разом з іншими обмеженнями вони дадуть необхідний ефект. Так, для розтягування по ширині контейнера застосовуються такі атрибути:
android:layout_width="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
А для розтягування по висоті контейнера застосовуються такі атрибути:
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
Наприклад, розтягнення TextView по всій довжині та ширині контейнера:
<TextView
android:layout_width="0dp"
android:layout_height="0dp"
android:text="Hello Android"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
Мінімальні та максимальні розміри
Низка атрибутів задають максимальні та мінімальні розміри:
layout_constraintWidth_minіlayout_constraintHeight_min: представляють відповідно мінімальну ширину і висотуlayout_constraintWidth_maxіlayout_constraintHeight_max: представляють відповідно максимальну ширину і висоту
Як значення вони приймають точне значення в dp або значення wrap (аналогічно wrap_content). Наприклад:
<TextView
android:layout_width="260dp"
android:layout_height="wrap_content"
android:text="Hello Android"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintHeight_max="200dp"
app:layout_constraintWidth_max="200dp"
app:layout_constraintHeight_min="wrap"
app:layout_constraintWidth_min="wrap"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
Хоча в цьому разі ширина TextView встановлена в 260dp, оскільки максимальна ширина задана в 200dp, то реальна ширина не перевищить 200dp.
Розміри у відсотках
Атрибут layout_constraintWidth_percent задає ширину елемента у відсотках по відношенню до доступного простору по горизонталі. Аналогічно атрибут layout_constraintHeight_percent задає висоту у відсотках щодо доступного простору по вертикалі.
Для їх застосування необхідно дотриматися таких умов:
- Відповідний атрибут для встановлення розміру (
android:layout_width- якщо ми встановлюємо ширину абоandroid:layout_height- якщо ми встановлюємо висоту у відсотках) повинен мати значенняMATCH_CONSTRAINTабо0dp. - Також необхідно встановити атрибут
app:layout_constraintWidth_default="percent"при встановленні ширини іapp:layout_constraintHeight_default="percent"при встановленні висоти. - Як значення атрибути
layout_constraintWidth_percentіlayout_constraintHeight_percentприймають дробове число від0до1.
Наприклад, нехай TextView займає по вертикалі 25%, а по горизонталі 50% простору:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="0dp"
android:layout_height="0dp"
android:text="Hello Android"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintWidth_default="percent"
app:layout_constraintHeight_default="percent"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintHeight_percent="0.25"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

Інший приклад - пропорційний поділ простору між кількома елементами:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/editText"
android:hint="Введите Email"
android:layout_height="wrap_content"
android:layout_width="0dp"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.66"
app:layout_constraintRight_toLeftOf="@+id/button"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:text="Отправить"
android:layout_height="wrap_content"
android:layout_width="0dp"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.33"
app:layout_constraintLeft_toRightOf="@id/editText"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
У цьому разі текстове поле EditText займатиме 66%, а кнопка - 33% ширини:

Встановлення співвідношення висоти та ширини
ConstraintLayout також дає змогу встановлювати в елементів висоту відносно ширини / ширину відносно висоти. Для цього застосовується атрибут layout_constraintDimensionRatio. Як значення він приймає відношення у вигляді Width:Height, наприклад, 1:0.5 - тут число 1 представляє ширину, а 0.5 - висоту. Тобто ширина буде вдвічі більшою за висоту. Але при цьому хоча б для одного виміру має бути встановлено 0dp (MATCH_CONSTRAINT). Наприклад:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="Hello Android"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintDimensionRatio="1:0.6"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
У цьому разі ширина TextView буде такою, яка необхідна для його вмісту, а висота 60% від ширини.

Якщо і для ширини, і для висоти встановлено 0dp, то в цьому випадку система вибере найбільший вимір, що відповідає всім обмеженням, і відносно нього встановить значення іншого виміру. Щоб конкретизувати вимір, щодо якого йтиме розрахунок, можна вказати символ W (ширина) або H (висота). Наприклад:
<TextView
android:layout_width="0dp"
android:layout_height="0dp"
android:text="Hello Android"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintDimensionRatio="W, 1:4"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
У цьому разі ширина буде в 4 рази меншою за висоту.