Explicăm elementele de bază ale LinearLayout — ViewGroup de bază în Android SDK pentru alinierea elementelor copil într-o singură linie: vertical (LinearLayout.VERTICAL) sau orizontal (LinearLayout.HORIZONTAL). LinearLayout rămâne cel mai simplu și rapid mod de a construi un rând de butoane, o listă de setări sau un formular de intrare, când complexitatea layout-ului nu depășește 5–10 elemente. Atributele layout_weight și orientation controlează distribuția spațiului și direcția. Specificația detaliată — în LinearLayout API Reference.
Principalele puncte
LinearLayout — una dintre primele ViewGroup din Android SDK (API Level 1), destinată plasării secvențiale a elementelor copil într-un singur rând sau coloană. Fiecare element nou este plasat după cel precedent, iar direcția este stabilită prin atributul android:orientation. LinearLayout este cel mai simplu și mai previzibil container Android, ceea ce îl face alegerea ideală pentru interfețe liniare: rânduri de butoane, liste de setări cu pictogramă și text, meniuri orizontale.
Istoric, LinearLayout este primul ViewGroup cu care se familiarizează un dezvoltator Android începător. Avantajul său este transparența: elementele copil sunt plasate strict în ordinea declarării, fără reguli ascunse de poziționare. Spre deosebire de RelativeLayout, unde un element poate fi legat de orice vecin, sau ConstraintLayout cu sistemul său de constrângeri, LinearLayout funcționează pe principiul „primul la stânga/sus, al doilea după el, al treilea după al doilea”. Conform Google I/O 2017, 78% din ecranele din top 1000 de aplicații Google Play folosesc LinearLayout ca container principal sau auxiliar.
Metrica principală a LinearLayout — LinearLayout.MeasureSpec — sistemul de gestionare a dimensiunii. La orientarea VERTICAL lățimea fiecărui element este egală cu lățimea părintelui (match_parent sau fixă), iar înălțimea este determinată de conținut sau de atribut. Pentru HORIZONTAL invers: înălțimea este egală cu cea a părintelui, lățimea — după conținut. Dacă într-un rând HORIZONTAL lățimea totală a elementelor depășește lățimea părintelui, elementele pot ieși în afara ecranului (dacă nu se folosește weight).
LinearLayout suprascrie onMeasure și onLayout din ViewGroup. La orientarea VERTICAL, onLayout plasează elementele pe axa Y: primul child — y=0, al doilea — y=prev.bottom + divider.hidden și așa mai departe. La HORIZONTAL — pe axa X. Divider (separatorul) se setează prin android:divider și android:showDividers (beginning, middle, end). Separatorul poate fi o culoare, un drawable sau o resursă Shape personalizată.
Orientarea — atributul cheie al LinearLayout care determină direcția de plasare a elementelor copil. android:orientation="vertical" aranjează elementele de sus în jos; android:orientation="horizontal" — de la stânga la dreapta (sau de la dreapta la stânga la localizarea RTL). Dacă orientarea nu este setată, implicit se folosește HORIZONTAL (pe versiunile vechi) — dar specificarea explicită este obligatorie pentru un comportament previzibil.
android:gravity — alinierea conținutului în interiorul LinearLayout. Acceptă combinații: top, bottom, left, right, center, center_horizontal, center_vertical, fill, clip_vertical, clip_horizontal. Valoarea gravity="center" pentru un layout VERTICAL va plasa toate elementele centrat pe orizontală. android:layout_gravity — atributul elementului copil care îl aliniază în interiorul LinearLayout părinte. Exemplu: un buton cu layout_gravity="right" într-un layout VERTICAL va fi lipit de marginea dreaptă.
Diferența: gravity — proprietatea părintelui (cum sunt dispuși copiii în interiorul său), layout_gravity — proprietatea copilului (cum se comportă în interiorul părintelui). Greșeala de a confunda aceste atribute este una dintre cele mai frecvente la începători.
Pentru layout-urile HORIZONTAL cu elemente text (TextView, Button, EditText) este util android:baselineAligned="true" — aliniază toate textele după linia de bază a fontului, indiferent de padding, size sau height. Acest lucru face ca un rând cu pictogramă, titlu și descriere să fie vizual îngrijit: textul nu sare în sus și în jos.
layout_weight — atributul elementului copil al LinearLayout care determină ce parte din spațiul liber va ocupa. Funcționează doar în direcția orientării (lățimea pentru HORIZONTAL, înălțimea pentru VERTICAL). Formula de calcul: dimensiune = dimensiune proprie + (spațiu liber × (greutatea elementului / suma tuturor greutăților)). Spațiul liber = dimensiunea părintelui — suma tuturor dimensiunilor proprii ale copiilor.
layout_weight este mai eficient decât dimensiunile fixe pentru interfețe adaptive. De exemplu, dacă panoul din stânga trebuie să ocupe 30% din ecran, iar cel din dreapta — 70%, setați weight=3 și weight=7. Pentru o funcționare corectă, de obicei se setează dimensiunea în direcție la 0dp (android:layout_width="0dp" pentru HORIZONTAL), astfel dimensiunea proprie a elementului este considerată zero, iar întreaga dimensiune este determinată doar de weight. Aceasta este recomandarea standard Google (Android Developers Guide, 2024).
Important: greutățile se însumează pentru toate elementele din LinearLayout, inclusiv cele fără weight (greutatea lor este considerată 0). Dacă un element are weight=1, iar altul weight=2, primul va ocupa 1/3 din spațiul liber, al doilea — 2/3. weightSum (atributul părintelui) permite setarea sumei maxime a greutății — dacă greutățile copiilor în sumă sunt mai mici decât weightSum, diferența rămâne ca spațiu gol.
Formularul de autentificare constă din trei elemente: câmpul email (ocupă 2/4), câmpul parolă (1/4) și butonul (1/4) din înălțimea ecranului. Toate cele trei elemente cu weight funcționează doar în orientarea VERTICAL pe înălțime.
<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="Parolă"
android:inputType="textPassword" />
<Button
android:id="@+id/login_button"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Autentificare" />
</LinearLayout>
Înălțimea fiecărui element = (parent_height — padding) × (weight / sumWeights). email va primi 2/4 din înălțime, parola și butonul — câte 1/4. Toate height=0dp, deci dimensiunea proprie nu este luată în considerare — funcționează doar weight.
Panou cu trei butoane: pictogramă înapoi (wrap_content), titlu (fill restul) și pictogramă meniu (wrap_content). weight pentru titlu = 1, butoanele fără weight.
<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="Titlu"
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>
Butoanele înapoi și meniu ocupă exact cât este necesar pentru pictogramă. Titlul (TextView) cu width=0dp și weight=1 se întinde pe tot spațiul rămas între ele. gravity="center_vertical" aliniază toate elementele pe centrul vertical.
Cartea produsului: rând orizontal (imagine + bloc vertical de text). LinearLayout exterior HORIZONTAL, interior — VERTICAL pentru titlu, descriere și preț.
<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="Denumirea produsului"
android:textStyle="bold"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Descrierea scurtă a produsului în două rânduri"
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>
Imaginea în stânga (80×80dp), în dreapta — bloc vertical din trei rânduri de text. LinearLayout interior are weight=1, deci ocupă tot spațiul rămas după imagine. Acesta este un model clasic de card de listă, întâlnit în mii de aplicații.
Principalul dezavantaj al LinearLayout — necesitatea containerelor încuibate pentru layout-uri complexe. Dacă trebuie să plasați elemente într-o rețea 2×2 sau să faceți un rând cu aliniere la două margini, sunt necesare cel puțin 2–3 niveluri de încuibare. Fiecare nivel de LinearLayout adaugă 2 treceri onMeasure, ceea ce pe dispozitivele slabe duce la blocări vizibile la randare.
Conform Android Performance Blog (Google, 2017), fiecare nivel suplimentar de încuibare crește timpul de layout cu 30–50 μs. Pentru o listă de 20 de elemente cu 3 niveluri de încuibare, întârzierea poate ajunge la 3 ms per element — acesta este un jank vizibil la derulare. ConstraintLayout rezolvă această problemă printr-o ierarhie plată, înlocuind 3–4 LinearLayout-uri încuibate cu un singur container cu constrângeri.
Recomandare: folosiți LinearLayout pentru layout-uri liniare simple (până la 10 elemente, un nivel de încuibare). Pentru carduri de listă, formulare cu aliniere diferită și ecrane cu structură tabelară, alegeți ConstraintLayout. Pentru elemente repetitive în RecyclerView, folosiți ConstraintLayout în fișierul layout al elementului — acest lucru este esențial pentru performanța derulării.
Întrebări frecvente
Cea mai frecventă cauză — nu este setată dimensiunea în direcție la 0dp. Pentru un layout HORIZONTAL este necesar android:layout_width="0dp", pentru VERTICAL — android:layout_height="0dp". Dacă elementul are wrap_content sau match_parent, weight poate să nu funcționeze sau să dea un rezultat neașteptat. A doua cauză — weightSum pe părinte este mai mic decât suma weight-urilor copiilor. A treia — utilizarea match_parent pe un element copil în direcția opusă.
layout_weight se setează pe fiecare element copil și determină cota sa din spațiul liber. weightSum — atributul părintelui LinearLayout care setează suma maximă a greutăților. Implicit, weightSum = suma tuturor layout_weight ale copiilor. Dacă setați weightSum = 3, iar copiii cu weight=1, fiecare va ocupa 1/3. Dacă sunt doar doi copii cu weight=1, 1/3 rămasă va fi goală. weightSum este convenabil pentru fixarea proporțiilor fără recalculare la adăugarea/eliminarea elementelor.
Implicit nu există spații — elementele sunt plasate una lângă alta. Dacă au apărut spații, verificați: android:divider și android:showDividers pe părinte, android:layout_margin pe elementele copil. Suplimentar poate influența android:weightSum — dacă elementele folosesc weight, între ele poate rămâne spațiu gol din cauza unui calcul incorect. Pentru spații zero, setați tuturor copiilor margin=0dp și eliminați divider.
Pentru layout-uri simple unidirecționale (1–5 elemente pe rând/coloană) LinearLayout este puțin mai rapid — nu consumă resurse pentru calcularea constrângerilor. Pentru layout-uri complexe (mai mult de 5 elemente, rețele, diferite tipuri de aliniere) ConstraintLayout este mai rapid, deoarece folosește o ierarhie plată în loc de LinearLayout-uri încuibate. Conform testelor Google (Android Performance Blog), ConstraintLayout câștigă pe layout-uri care necesită 3+ niveluri de încuibare LinearLayout.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și