Все визуальные элеметы, которые мы используем в приложении, как правило, упорядочиваются на экране с помощью контейнеров. В Android подобными контейнерами служат такие классы как RelativeLayout, LinearLayout, GridLayout, TableLayout, ConstraintLayout, FrameLayout. Все они по разному располагают элементы и управляют ими, но есть некоторые общие моменты при компоновке визуальных компонентов, которые мы сейчас рассмотрим.
Для организации элементов внутри контейнера используются параметры разметки. Для их задания в файле xml используются атрибуты, которые начинаются с префикса layout_. В частности, к таким параметрам относятся атрибуты layout_height и layout_width, которые используются для установки размеров и могут использовать одну из следующих опций:
Растяжение по всей ширине или высоте контейнера с помощью значения match_parent (для всех контейнеров кроме ConstraintLayout) или 0dp (для ConstraintLayout)
Растяжение элемента до тех границ, которые достаточны, чтобы вместить все его содержимое с помощью значения wrap_content
Точные размеры элемента, например 96 dp
Установка значения match_parent позволяет растянуть элемент по всей ширине или высоте контейнера. Стоит отметить, что данное значение применяется ко всем контейнерам, кроме ConstraintLayout. Например, рястянем элемент TextView по всей ширине и высоте контейнера LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello World!"
android:textSize="30sp"
android:background="#e0e0e0" />
</LinearLayout>
Контейнер самого верхнего уровня, в качестве которого в данном случае выступает LinearLayout, для высоты и ширины имеет значение match_parent, то есть он будет заполнять всю область для activity - как правило, весь экран.
И TextView также принимает подобные атрибуты. Значение android:layout_width="match_parent" обеспечивает растяжение по ширине, а
android:layout_height="match_parent" - по вертикали. Для наглядности в TextView применяет атрибут android:background, который представляет фон и в данном случае окрашивает элемент
в цвет "#e0e0e0", благодаря чему мы можем увидеть занимаемую им область.
Следует учитывать, что значение match_parent можно применять почти во всех встроенных контейнерах, типа LinearLayout или RelativeLayout и их элементах. Однако match_parent не рекомендуется применять к элементам внутри ConstraintLayout. Вместо "match_parent" в ConstraintLayout можно использовать значение 0dp, чтобы растянуть элемент по горизонтали или вертикали:
<?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 World!"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
Стоит отметить, что ConstraintLayout сама также растягивается по ширине и высоте экрана с помощью значения "match_parent" в атрибутах
layout_width и android:layout_height, но к вложенным элементам это значение не рекомендуется применять.
Поскольку ConstraintLayout имеет некоторые особенности при установке размеров, то более подробно работа с размерами элементов именно в ConstraintLayout раскрыта более подробно в одной из следующих тем.
Значение wrap_content устанавливает те значения для ширины или высоты, которые необходимы, чтобы разместить на экране содержимое элемента:
<?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="wrap_content"
android:text="Hello World!"
android:textSize="30sp"
android:background="#ffcdd2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
Здесь элемент TextView растягивается до тех значений, которые достаточны для размещения его текста.
Также мы можем установить точные значения:
<?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_height="90dp"
android:layout_width="150dp"
android:text="Hello World!"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
Кроме того, можно комбинировать несколько значений, например, растянуть по ширине содержимого и установить точные значения для высоты:
<TextView
android:layout_height="80dp"
android:layout_width="wrap_content"
android:text="Hello World!"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
Если для установки ширины и длины используется значение wrap_content, то мы можем дополнительно ограничить минимальные и максимальные значения с помощью атрибутов minWidth/maxWidth и minHeight/maxHeight:
<TextView
android:minWidth="200dp"
android:maxWidth="250dp"
android:minHeight="100dp"
android:maxHeight="200dp"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Hello World!"
android:textSize="30sp"
android:background="#e0e0e0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
В этом случае ширина TextView будет такой, которая достаточна для вмещения текста, но не больше значения maxWidth и не меньше значения minWidth. То же самое для установки высоты.
Если элемент, к примеру, тот же TextView создается в коде java, то для установки высоты и ширины можно использовать метод setLayoutParams(). Так, изменим код MainActivity:
package com.example.viewapp;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ConstraintLayout constraintLayout = new ConstraintLayout(this);
TextView textView = new TextView(this);
textView.setText("Hello Android");
textView.setTextSize(26);
// устанавливаем параметры размеров и расположение элемента
ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams
(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT);
// эквивалент app:layout_constraintLeft_toLeftOf="parent"
layoutParams.leftToLeft = ConstraintLayout.LayoutParams.PARENT_ID;
// эквивалент app:layout_constraintTop_toTopOf="parent"
layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;
// устанавливаем параметры для textView
textView.setLayoutParams(layoutParams);
// добавляем TextView в ConstraintLayout
constraintLayout.addView(textView);
setContentView(constraintLayout);
}
}
В метод setLayoutParams() передается объект ViewGroup.LayoutParams. Этот объект инициализируется двумя параметрами: шириной и высотой.
Для указания ширины и высоты можно использовать одну из констант ViewGroup.LayoutParams.WRAP_CONTENT или
ViewGroup.LayoutParams.MATCH_PARENT (в случае с LinearLayout или RelativeLayout).
Поскольку в данном случае мы имеем дело с контейнером ConstraintLayout, то для установки размеров применяется значение ConstraintLayout.LayoutParams.WRAP_CONTENT. В реальности
класс androidx.constraintlayout.widget.ConstraintLayout.LayoutParams, который предоставляет это значение, наследуется от android.view.ViewGroup.LayoutParams
Также мы можем передать точные значения или комбинировать типы значений:
ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams
(ConstraintLayout.LayoutParams.WRAP_CONTENT, 200);