LinearLayout: podstawy, orientacja i rozkład wag w Androidzie

Autor: IT Sectr Opublikowano: 2026-02-24 Czas czytania: 9 min

Wyjaśniamy podstawy LinearLayout — podstawowej ViewGroup w Android SDK do wyrównywania elementów potomnych w jednej linii: pionowo (LinearLayout.VERTICAL) lub poziomo (LinearLayout.HORIZONTAL). LinearLayout pozostaje najprostszym i najszybszym sposobem na zbudowanie wiersza przycisków, listy ustawień lub formularza wejściowego, gdy złożoność układu nie przekracza 5–10 elementów. Atrybuty layout_weight i orientation zarządzają rozkładem przestrzeni i kierunkiem. Szczegółowa specyfikacja — w LinearLayout API Reference.

Najważniejsze

  • Orientacja — LinearLayout umieszcza elementy sekwencyjnie pionowo (VERTICAL) lub poziomo (HORIZONTAL), ustawiane przez android:orientation.
  • layout_weight — rozkład wolnej przestrzeni proporcjonalnie do wagi elementów; suma wag określa udział każdego.
  • gravity vs layout_gravity — android:gravity wyrównuje zawartość wewnątrz LinearLayout; android:layout_gravity wyrównuje sam element wewnątrz rodzica.
  • Zagnieżdżanie — główna wada: dla złożonej siatki wymagane jest zagnieżdżenie kilku LinearLayout, co obniża wydajność.
  • Baseline alignment — wyrównywanie elementów tekstowych według linii bazowej czcionki niezależnie od padding i wysokości elementu.

Co to jest LinearLayout?

LinearLayout — jedna z pierwszych ViewGroup w Android SDK (API Level 1), przeznaczona do sekwencyjnego umieszczania elementów potomnych w jednym wierszu lub kolumnie. Każdy nowy element znajduje się po poprzednim, a kierunek jest ustawiany atrybutem android:orientation. LinearLayout jest najprostszym i najbardziej przewidywalnym kontenerem Androida, co czyni go idealnym wyborem dla interfejsów liniowych: wierszy przycisków, list ustawień z ikoną i tekstem, poziomych menu.

Historycznie LinearLayout to pierwsza ViewGroup, z którą zapoznaje się początkujący programista Androida. Jego zaletą jest przejrzystość: elementy potomne są rozmieszczane ściśle w kolejności deklaracji, bez ukrytych zasad pozycjonowania. W przeciwieństwie do RelativeLayout, gdzie element może być powiązany z dowolnym sąsiadem, lub ConstraintLayout z jego systemem ograniczeń, LinearLayout działa na zasadzie „pierwszy z lewej/u góry, drugi po nim, trzeci po drugim”. Według Google I/O 2017, 78% ekranów w top 1000 aplikacji Google Play używa LinearLayout jako głównego lub pomocniczego kontenera.

Główna metryka LinearLayout — LinearLayout.MeasureSpec — system zarządzania rozmiarem. Przy orientacji VERTICAL szerokość każdego elementu jest równa szerokości rodzica (match_parent lub stała), a wysokość jest określana przez zawartość lub atrybut. Dla HORIZONTAL odwrotnie: wysokość jest równa rodzicielskiej, szerokość — według zawartości. Jeśli w wierszu HORIZONTAL całkowita szerokość elementów przekracza szerokość rodzica, elementy mogą wystawać poza ekran (jeśli nie używamy weight).

Budowa wewnętrzna

LinearLayout nadpisuje onMeasure i onLayout z ViewGroup. Przy orientacji VERTICAL onLayout umieszcza elementy na osi Y: pierwszy child — y=0, drugi — y=prev.bottom + divider.hidden, i tak dalej. Przy HORIZONTAL — na osi X. Divider (separator) jest ustawiany przez android:divider i android:showDividers (beginning, middle, end). Separator może być kolorem, drawable lub niestandardowym zasobem Shape.

Orientacja i Gravity: VERTICAL i HORIZONTAL

Orientacja — kluczowy atrybut LinearLayout określający kierunek rozmieszczania elementów potomnych. android:orientation="vertical" układa elementy od góry do dołu; android:orientation="horizontal" — od lewej do prawej (lub od prawej do lewej przy lokalizacji RTL). Jeśli orientacja nie jest ustawiona, domyślnie używana jest HORIZONTAL (w starszych wersjach) — ale jawne określenie jest obowiązkowe dla przewidywalnego zachowania.

android:gravity — wyrównywanie zawartości wewnątrz LinearLayout. Przyjmuje kombinacje: top, bottom, left, right, center, center_horizontal, center_vertical, fill, clip_vertical, clip_horizontal. Wartość gravity="center" dla układu VERTICAL umieści wszystkie elementy centralnie w poziomie. android:layout_gravity — atrybut elementu potomnego, wyrównujący go wewnątrz rodzicielskiego LinearLayout. Przykład: przycisk z layout_gravity="right" w układzie VERTICAL zostanie dociśnięty do prawej krawędzi.

Różnica: gravity — właściwość rodzica (jak dzieci są rozmieszczane wewnątrz), layout_gravity — właściwość dziecka (jak zachowuje się wewnątrz rodzica). Błąd polegający na pomyleniu tych atrybutów jest jednym z najczęstszych u początkujących.

Baseline alignment

Dla układów HORIZONTAL z elementami tekstowymi (TextView, Button, EditText) przydatny jest android:baselineAligned="true" — wyrównuje on wszystkie teksty według linii bazowej czcionki, niezależnie od ich padding, size lub height. Dzięki temu wiersz z ikoną, tytułem i opisem wygląda wizualnie schludnie: tekst nie skacze w górę i w dół.

layout_weight: rozkład wagi

layout_weight — atrybut elementu potomnego LinearLayout określający, jaką część wolnej przestrzeni zajmie. Działa tylko w kierunku orientacji (szerokość dla HORIZONTAL, wysokość dla VERTICAL). Wzór obliczeniowy: rozmiar = rozmiar własny + (wolna przestrzeń × (waga elementu / suma wszystkich wag)). Wolna przestrzeń = rozmiar rodzica — suma wszystkich rozmiarów własnych dzieci.

layout_weight jest bardziej efektywny niż stałe rozmiary dla interfejsów adaptacyjnych. Na przykład, jeśli lewy panel ma zajmować 30% ekranu, a prawy — 70%, ustaw weight=3 i weight=7. Do poprawnego działania zwykle ustawia się rozmiar w kierunku na 0dp (android:layout_width="0dp" dla HORIZONTAL), wtedy rozmiar własny elementu jest zerowy, a cały rozmiar jest określany tylko przez weight. Jest to standardowe zalecenie Google (Android Developers Guide, 2024).

Ważne: wagi sumują się dla wszystkich elementów w LinearLayout, włączając te, które nie mają ustawionego weight (ich waga jest liczona jako 0). Jeśli jeden element ma weight=1, a drugi weight=2, to pierwszy zajmie 1/3 wolnej przestrzeni, drugi — 2/3. weightSum (atrybut rodzica) pozwala ustawić maksymalną sumę wagi — jeśli sumaryczna waga dzieci jest mniejsza niż weightSum, różnica pozostaje jako pusta przestrzeń.

Przykłady kodu: układy XML

Przykład 1: Pionowy formularz z weight

Formularz logowania składa się z trzech elementów: pole email (zajmuje 2/4), pole hasła (1/4) i przycisk (1/4) wysokości ekranu. Wszystkie trzy elementy z weight działają tylko w orientacji VERTICAL względem wysokości.

xml
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <EditText
        android:id="@+id/email"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:hint="Email" />

    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:hint="Hasło"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/login_button"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="Zaloguj się" />

</LinearLayout>

Wysokość każdego elementu = (parent_height — padding) × (weight / sumWeights). email otrzyma 2/4 wysokości, hasło i przycisk — po 1/4. Wszystkie height=0dp, więc rozmiar własny nie jest uwzględniany — działa tylko weight.

Przykład 2: Poziomy pasek narzędzi

Panel z trzema przyciskami: ikona wstecz (wrap_content), tytuł (fill pozostałe) i ikona menu (wrap_content). weight dla tytułu = 1, przyciski bez weight.

xml
<LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="56dp"
    android:gravity="center_vertical">

    <ImageButton
        android:id="@+id/btn_back"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_arrow_back" />

    <TextView
        android:id="@+id/toolbar_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="Tytuł"
        android:textSize="18sp" />

    <ImageButton
        android:id="@+id/btn_menu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_more_vert" />

</LinearLayout>

Przyciski wstecz i menu zajmują dokładnie tyle, ile potrzeba dla ikony. Tytuł (TextView) z width=0dp i weight=1 rozciąga się na całą pozostałą przestrzeń między nimi. gravity="center_vertical" wyrównuje wszystkie elementy do pionowego środka.

Przykład 3: Zagnieżdżone LinearLayout dla złożonej karty

Karta produktu: poziomy wiersz (obraz + pionowy blok tekstu). Zewnętrzny LinearLayout HORIZONTAL, wewnętrzny — VERTICAL dla tytułu, opisu i ceny.

xml
<LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="8dp">

    <ImageView
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:src="@drawable/product_image"
        android:scaleType="centerCrop" />

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_marginStart="12dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Nazwa produktu"
            android:textStyle="bold"
            android:textSize="16sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Krótki opis produktu w dwóch liniach"
            android:textSize="14sp"
            android:textColor="@color/gray" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="1 299 rub."
            android:textSize="18sp"
            android:textColor="@color/accent" />

    </LinearLayout>

</LinearLayout>

Obraz z lewej strony (80×80dp), z prawej — pionowy blok z trzema wierszami tekstu. Wewnętrzny LinearLayout ma weight=1, więc zajmuje całe pozostałe miejsce po obrazie. Jest to klasyczny wzorzec karty listy, który występuje w tysiącach aplikacji.

Problem zagnieżdżania i alternatywy

Główna wada LinearLayout — konieczność zagnieżdżania kontenerów dla złożonych układów. Jeśli trzeba rozmieścić elementy w siatce 2×2 lub zrobić wiersz z wyrównaniem do dwóch krawędzi, wymagane są co najmniej 2–3 poziomy zagnieżdżenia. Każdy poziom LinearLayout dodaje 2 przejścia onMeasure, co na słabych urządzeniach prowadzi do zauważalnych zacięć przy rysowaniu.

Według Android Performance Blog (Google, 2017), każdy dodatkowy poziom zagnieżdżenia zwiększa czas układu o 30–50 μs. Dla listy 20 elementów z 3 poziomami zagnieżdżenia opóźnienie może osiągnąć 3 ms na element — jest to zauważalny jank podczas przewijania. ConstraintLayout rozwiązuje ten problem poprzez płaską hierarchię, zastępując 3–4 zagnieżdżone LinearLayout jednym kontenerem z ograniczeniami.

Zalecenie: używaj LinearLayout do prostych układów liniowych (do 10 elementów, jeden poziom zagnieżdżenia). Dla kart list, formularzy z różnym wyrównaniem i ekranów z strukturą tabelaryczną wybieraj ConstraintLayout. Dla powtarzających się elementów w RecyclerView używaj ConstraintLayout w pliku układu elementu — jest to kluczowe dla wydajności przewijania.

Często zadawane pytania

Dlaczego layout_weight nie działa?

Najczęstsza przyczyna — nie ustawiono rozmiaru w kierunku na 0dp. Dla układu HORIZONTAL potrzebne jest android:layout_width="0dp", dla VERTICAL — android:layout_height="0dp". Jeśli element ma wrap_content lub match_parent, weight może nie zadziałać lub dać nieoczekiwany wynik. Drugą przyczyną jest weightSum na rodzicu mniejszy niż suma wag dzieci. Trzecią — użycie match_parent na elemencie potomnym w przeciwnym kierunku.

Jaka jest różnica między layout_weight a weightSum?

layout_weight jest ustawiany na każdym elemencie potomnym i określa jego udział w wolnej przestrzeni. weightSum — atrybut rodzica LinearLayout, który ustawia maksymalną sumę wag. Domyślnie weightSum = sumie wszystkich layout_weight dzieci. Jeśli ustawisz weightSum = 3, a children z weight=1, każdy zajmie 1/3. Jeśli dzieci z weight=1 jest tylko dwoje, pozostała 1/3 będzie pusta. weightSum jest wygodny do ustalania proporcji bez przeliczania przy dodawaniu/usuwaniu elementów.

Jak usunąć odstępy między elementami LinearLayout?

Domyślnie nie ma odstępów — elementy są umieszczone bezpośrednio obok siebie. Jeśli odstępy się pojawiły, sprawdź: android:divider i android:showDividers na rodzicu, android:layout_margin na elementach potomnych. Dodatkowo może wpływać android:weightSum — jeśli elementy używają weight, między nimi może pozostawać pusta przestrzeń z powodu błędnego obliczenia. Dla zerowych odstępów ustaw wszystkim potomnym margin=0dp i usuń divider.

Co jest szybsze: LinearLayout czy ConstraintLayout?

Dla prostych jednokierunkowych układów (1–5 elementów w wierszu/kolumnie) LinearLayout jest nieco szybszy — nie traci zasobów na obliczanie ograniczeń. Dla złożonych układów (ponad 5 elementów, siatki, różne typy wyrównania) ConstraintLayout jest szybszy, ponieważ używa płaskiej hierarchii zamiast zagnieżdżonych LinearLayout. Według testów Google (Android Performance Blog), ConstraintLayout wygrywa na układach wymagających 3+ poziomów zagnieżdżenia LinearLayout.

Podsumowanie

  • LinearLayout — podstawowa ViewGroup Androida do sekwencyjnego umieszczania elementów pionowo lub poziomo.
  • Orientacja — android:orientation="vertical" (kolumna) lub "horizontal" (wiersz) określa kierunek układu.
  • layout_weight — mechanizm rozkładu wolnej przestrzeni proporcjonalnie do wagi elementów z rozmiarami w 0dp.
  • Gravity — android:gravity (wyrównanie dzieci wewnątrz rodzica) vs android:layout_gravity (wyrównanie dziecka w rodzicu).
  • Zagnieżdżanie — główna wada: dla złożonych układów wymagane są 2–3 poziomy, co spowalnia rysowanie o 30–50 μs na poziom.
  • Wybór — LinearLayout dla prostych wierszy/kolumn (do 10 elementów), ConstraintLayout dla złożonych układów.
  • Adaptacyjność — kombinacja weight + 0dp + baseline alignment pokrywa 80% zadań układu liniowego.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również