LinearLayout
Контейнер LinearLayout представляє найпростіший контейнер - об'єкт ViewGroup, який упорядковує всі дочірні елементи в одному напрямку: по горизонталі або по вертикалі. Усі елементи розташовані один за одним. Напрямок розмітки вказується за допомогою атрибута android:orientation.
Якщо, наприклад, орієнтація розмітки вертикальна (android:orientation="vertical"), то всі елементи розташовуються в стовпчик - по одному елементу на кожному рядку. Якщо орієнтація горизонтальна (android:orientation="horizontal"), то елементи розташовуються в один рядок. Наприклад, розташуємо елементи в горизонтальний ряд:
<?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"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Hello"
android:textSize="26sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Android"
android:textSize="26sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="World"
android:textSize="26sp" />
</LinearLayout>
Якби ми вказали для LinearLayout атрибут android:orientation="vertical", то елементи розміщувалися б по вертикалі:

Вага елемента
LinearLayout підтримує таку властивість, як вага елемента, яка передається атрибутом android:layout_weight. Ця властивість приймає значення, що вказує, яку частину вільного місця контейнера, що залишилося, стосовно інших об'єктів займе цей елемент. Наприклад, якщо один елемент у нас матиме для властивості android:layout_weight значення 2, а інший - значення 1, то в сумі вони дадуть 3, тому перший елемент займатиме 2/3 решти простору, а другий - 1/3.
Якщо всі елементи мають значення android:layout_weight="1", то всі ці елементи будуть рівномірно розподілені по всій площі контейнера:
<?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"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="Hello"
android:background="#e0e0e0"
android:layout_weight="1"
android:textSize="26sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#eeeeee"
android:text="Android"
android:layout_weight="1"
android:textSize="26sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="World"
android:background="#bdbdbd"
android:layout_weight="1"
android:textSize="26sp" />
</LinearLayout>
У цьому випадку LinearLayout має вертикальну орієнтацію, тому всі елементи розташовуватимуться зверху вниз. Усі три елементи мають значення android:layout_weight="1", тому сума ваг усіх елементів дорівнюватиме 3, а кожен елемент отримає по третині простору в LinearLayout:

При цьому оскільки у нас вертикальний стек, то нам треба також встановити для властивості layout_height значення 0dp. Якби LinearLayout мав горизонтальну орієнтацію, то для властивості layout_width треба було б встановити значення 0dp.
Ще один атрибут android:weightSum дає змогу вказати суму ваг усіх елементів. Наприклад:
<?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"
android:orientation="vertical"
android:weightSum="7">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="Hello"
android:background="#e0e0e0"
android:layout_weight="1"
android:textSize="26sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#eeeeee"
android:text="Android"
android:layout_weight="3"
android:textSize="26sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="World"
android:background="#bdbdbd"
android:layout_weight="2"
android:textSize="26sp" />
</LinearLayout>
LinearLayout тут задає суму ваг рівну 7. Тобто весь простір по вертикалі (оскільки вертикальна орієнтація) умовно ділиться на сім рівних частин.
Перший TextView має вагу 1, тобто з цих семи частин займає тільки одну. Другий TextView має вагу 3, тобто займає три частини із семи. І третій має вагу 2. Підсумкова сума становить 6. Але оскільки LinearLayout задає вагу 7, то одна частина буде вільна від усіх елементів.

Програмне створення LinearLayout
package com.example.viewapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
LinearLayout linearLayout = new LinearLayout(this);
// горизонтальна орієнтація
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
TextView textView = new TextView(this);
textView.setText("Hello");
textView.setTextSize(30);
// створюємо параметри позиціонування для елемента
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
// встановлюємо відступи
layoutParams.setMargins(100, 100, 0, 0);
textView.setLayoutParams(layoutParams);
// додаємо елемент у LinearLayout
linearLayout.addView(textView);
setContentView(linearLayout);
}
}

Додаткова версія конструктора LinearLayout.LayoutParams() як третій параметр дає змогу вказати вагу елемента:
package com.example.viewapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.VERTICAL);
// перше текстове поле
TextView textView1 = new TextView(this);
textView1.setText("Hello");
textView1.setTextSize(30);
// textView1 має вагу 3
linearLayout.addView(textView1, new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.MATCH_PARENT, 0, 3));
// второе текстовое поле
TextView textView2 = new TextView(this);
textView2.setText("Android");
textView2.setBackgroundColor(0xFFBDBDBD);
textView2.setTextSize(30);
// textView2 має вагу 2
linearLayout.addView(textView2, new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.MATCH_PARENT, 0, 2));
setContentView(linearLayout);
}
}

Layout_gravity
Атрибут layout_gravity дає змогу встановлювати позиціонування щодо LinearLayout. Він приймає такі значення:
top: вирівнює елемент по верхній межі контейнераbottom: вирівнює елемент по нижній межі контейнераleft: вирівнює елемент по лівій межі контейнераright: вирівнює елемент по правій межі контейнераcenter_vertical: вирівнює елемент по центру по вертикаліcenter_horizontal: вирівнює елемент по центру по горизонталіcenter: елемент позиціонується в центріfill_vertical: елемент розтягується по вертикаліfill_horizontal: елемент розтягується по горизонталіfill: елемент заповнює весь простір контейнераclip_vertical: обрізає верхню і нижню межу елементаclip_horizontal: обрізає праву і ліву межу елементаstart: елемент позиціонується на початку (у верхньому лівому кутку) контейнераend: елемент позиціонується в кінці контейнера (у верхньому правому куті)
Наприклад:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_gravity="left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Hello Java!"
android:background="#e8eaf6"/>
<TextView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Hello World!"
android:background="#e8eaf6"/>
<TextView
android:layout_gravity="right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Hello Android!"
android:background="#e8eaf6"/>
<TextView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Hello Kotlin!"
android:background="#e8eaf6"/>
</LinearLayout>
У цьому випадку перший елемент TextView буде позиціонуватися по лівому боці контейнера (android:layout_gravity="left"), другий TextView по центру (android:layout_gravity="center"), третій - по правому боці (android:layout_gravity="right") та четвертий - по центру (android:layout_gravity="center").

Варто враховувати орієнтацію контейнера. Наприклад, за вертикальної орієнтації всі елементи представлятимуть вертикальний стек, що йде зверху вниз. Тому значення, які відносяться до позиціонування елемента по вертикалі (наприклад, top або bottom) ніяк не впливатимуть на елемент. Також за горизонтальної орієнтації LinearLayout не матимуть жодного впливу значення, які позиціонують елемент по горизонталі, наприклад, left і right.
Для встановлення програмно параметра layout_gravity треба задати поле gravity в об'єкта LinearLayout.LayoutParams:
package com.example.viewapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
// установка layout_gravity
layoutParams.gravity = Gravity.CENTER;
// перше текстове поле
TextView textView1 = new TextView(this);
textView1.setText("Hello");
textView1.setTextSize(30);
linearLayout.addView(textView1, layoutParams);
setContentView(linearLayout);
}
}
Як значення передається одна з констант класу Gravity, які аналогічні значенням атрибута.
Приклад
<?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"
android:orientation="vertical"
android:padding="16dp">
<!-- Заголовок екрана -->
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Оформлення замовлення"
android:textSize="20sp"
android:textStyle="bold"
android:gravity="center"
android:layout_marginBottom="16dp" />
<!-- Поле для введення імені -->
<EditText
android:id="@+id/nameInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Ім'я клієнта"
android:inputType="textPersonName"
android:layout_marginBottom="8dp" />
<!-- Поле для введення номера телефону -->
<EditText
android:id="@+id/phoneInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Телефон"
android:inputType="phone"
android:layout_marginBottom="16dp" />
<!-- Горизонтальне вирівнювання для вибору способу доставки -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<!-- Варіант "Самовивіз" -->
<RadioButton
android:id="@+id/pickupOption"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Самовивіз" />
<!-- Варіант "Доставка" -->
<RadioButton
android:id="@+id/deliveryOption"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Доставка" />
</LinearLayout>
<!-- Поле введення адреси для доставки -->
<EditText
android:id="@+id/addressInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Адреса доставки"
android:inputType="textPostalAddress"
android:layout_marginBottom="16dp"
android:visibility="gone" /> <!-- Спочатку приховано -->
<!-- Горизонтальне вирівнювання для кнопок -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="end">
<!-- Кнопка "Очистити" -->
<Button
android:id="@+id/clearButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Очистити"
android:layout_marginEnd="8dp" />
<!-- Кнопка "Оформити замовлення" -->
<Button
android:id="@+id/submitButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Оформити" />
</LinearLayout>
</LinearLayout>
Що використано в цьому прикладі
- Вертикальне розташування (
orientation="vertical")- Основний контейнер
LinearLayoutрозташовує всі елементи вертикально.
- Основний контейнер
- Вирівнювання тексту по центру (
gravity="center")- Заголовок
titleTextвирівняний горизонтально по центру.
- Заголовок
- Використання
layout_weightу вкладеному горизонтальному лейауті- У секції вибору способу доставки (
RadioButton) кожен варіант займає рівну частину простору завдякиlayout_weight="1".
- У секції вибору способу доставки (
- Динамічне керування видимістю
- Поле введення адреси (
addressInput) приховане спочатку черезandroid:visibility="gone", і його можна показувати програмно.
- Поле введення адреси (
- Вирівнювання елементів усередині горизонтального контейнера
- Кнопки внизу вирівняні по правому краю через
android:gravity="end".
- Кнопки внизу вирівняні по правому краю через
- Міжелементні відступи (
layout_margin)- Додано відступи для візуального розділення елементів.
Реальний сценарій
Цей інтерфейс можна використати в бізнес-застосунку для оформлення замовлення:
- Клієнт вводить своє ім’я та телефон.
- Вибирає спосіб доставки (самовивіз або доставка).
- Якщо вибрано доставку, програмно відображається поле введення адреси.
- Кнопки "Очистити" та "Оформити" дозволяють або очистити введені дані, або завершити оформлення замовлення.
