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>

Що використано в цьому прикладі

  1. Вертикальне розташування (orientation="vertical")
    • Основний контейнер LinearLayout розташовує всі елементи вертикально.
  2. Вирівнювання тексту по центру (gravity="center")
    • Заголовок titleText вирівняний горизонтально по центру.
  3. Використання layout_weight у вкладеному горизонтальному лейауті
    • У секції вибору способу доставки (RadioButton) кожен варіант займає рівну частину простору завдяки layout_weight="1".
  4. Динамічне керування видимістю
    • Поле введення адреси (addressInput) приховане спочатку через android:visibility="gone", і його можна показувати програмно.
  5. Вирівнювання елементів усередині горизонтального контейнера
    • Кнопки внизу вирівняні по правому краю через android:gravity="end".
  6. Міжелементні відступи (layout_margin)
    • Додано відступи для візуального розділення елементів.

Реальний сценарій

Цей інтерфейс можна використати в бізнес-застосунку для оформлення замовлення:

  1. Клієнт вводить своє ім’я та телефон.
  2. Вибирає спосіб доставки (самовивіз або доставка).
  3. Якщо вибрано доставку, програмно відображається поле введення адреси.
  4. Кнопки "Очистити" та "Оформити" дозволяють або очистити введені дані, або завершити оформлення замовлення.