LinearLayout: βασικά, προσανατολισμός και κατανομή βάρους στο Android

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-02-24 Χρόνος ανάγνωσης: 9 λεπ

Εξηγούμε τα βασικά του LinearLayout — βασική ViewGroup στο Android SDK για στοίχιση θυγατρικών στοιχείων σε μία γραμμή: κάθετα (LinearLayout.VERTICAL) ή οριζόντια (LinearLayout.HORIZONTAL). Το LinearLayout παραμένει ο απλούστερος και ταχύτερος τρόπος για να δημιουργήσετε μια γραμμή κουμπιών, μια λίστα ρυθμίσεων ή μια φόρμα εισαγωγής, όταν η πολυπλοκότητα της διάταξης δεν υπερβαίνει τα 5–10 στοιχεία. Τα χαρακτηριστικά layout_weight και orientation διαχειρίζονται την κατανομή του χώρου και την κατεύθυνση. Λεπτομερής προδιαγραφή — στο LinearLayout API Reference.

Κύρια σημεία

  • Προσανατολισμός — Το LinearLayout τοποθετεί τα στοιχεία διαδοχικά κάθετα (VERTICAL) ή οριζόντια (HORIZONTAL), που ορίζεται μέσω android:orientation.
  • layout_weight — κατανομή ελεύθερου χώρου ανάλογα με το βάρος των στοιχείων· το άθροισμα βαρών καθορίζει το μερίδιο του καθενός.
  • gravity vs layout_gravity — το android:gravity στοιχίζει το περιεχόμενο μέσα στο LinearLayout· το android:layout_gravity στοιχίζει το ίδιο το στοιχείο μέσα στον γονέα.
  • Ένθεση — το κύριο μειονέκτημα: για σύνθετο πλέγμα απαιτείται ένθεση πολλαπλών LinearLayout, που μειώνει την απόδοση.
  • Baseline alignment — στοίχιση στοιχείων κειμένου στη γραμμή βάσης της γραμματοσειράς ανεξάρτητα από padding και ύψος στοιχείου.

Τι είναι το LinearLayout;

LinearLayout — μία από τις πρώτες ViewGroup στο Android SDK (API Level 1), που προορίζεται για τη διαδοχική τοποθέτηση θυγατρικών στοιχείων σε μία γραμμή ή στήλη. Κάθε νέο στοιχείο τοποθετείται μετά το προηγούμενο και η κατεύθυνση ορίζεται από το χαρακτηριστικό android:orientation. Το LinearLayout είναι το απλούστερο και πιο προβλέψιμο δοχείο Android, καθιστώντας το ιδανική επιλογή για γραμμικές διεπαφές: γραμμές κουμπιών, λίστες ρυθμίσεων με εικονίδιο και κείμενο, οριζόντια μενού.

Ιστορικά, το LinearLayout είναι η πρώτη ViewGroup που γνωρίζει ένας αρχάριος προγραμματιστής Android. Το πλεονέκτημά του είναι η διαφάνεια: τα θυγατρικά στοιχεία τοποθετούνται αυστηρά με τη σειρά δήλωσης, χωρίς κρυφούς κανόνες τοποθέτησης. Σε αντίθεση με το RelativeLayout, όπου ένα στοιχείο μπορεί να συνδεθεί με οποιονδήποτε γείτονα, ή το ConstraintLayout με το σύστημα περιορισμών του, το LinearLayout λειτουργεί με την αρχή 'πρώτο αριστερά/πάνω, δεύτερο μετά από αυτό, τρίτο μετά το δεύτερο'. Σύμφωνα με το Google I/O 2017, το 78% των οθονών στις κορυφαίες 1000 εφαρμογές Google Play χρησιμοποιεί το LinearLayout ως κύριο ή βοηθητικό δοχείο.

Η κύρια μετρική του LinearLayout — LinearLayout.MeasureSpec — σύστημα διαχείρισης μεγέθους. Στον προσανατολισμό VERTICAL, το πλάτος κάθε στοιχείου είναι ίσο με το πλάτος του γονέα (match_parent ή σταθερό) και το ύψος καθορίζεται από το περιεχόμενο ή το χαρακτηριστικό. Για HORIZONTAL αντίστροφα: ύψος ίσο με το γονικό, πλάτος — ανάλογα με το περιεχόμενο. Αν σε μια γραμμή HORIZONTAL το συνολικό πλάτος των στοιχείων υπερβαίνει το πλάτος του γονέα, τα στοιχεία μπορεί να βγουν έξω από την οθόνη (αν δεν χρησιμοποιείται weight).

Εσωτερική δομή

Το LinearLayout παρακάμπτει τα onMeasure και onLayout από το ViewGroup. Στον προσανατολισμό VERTICAL, το onLayout τοποθετεί τα στοιχεία στον άξονα Y: πρώτο child — y=0, δεύτερο — y=prev.bottom + divider.hidden, και ούτω καθεξής. Στον HORIZONTAL — στον άξονα X. Το Divider (διαχωριστικό) ορίζεται μέσω android:divider και android:showDividers (beginning, middle, end). Το διαχωριστικό μπορεί να είναι χρώμα, drawable ή προσαρμοσμένος πόρος Shape.

Προσανατολισμός και Gravity: VERTICAL και HORIZONTAL

Προσανατολισμός — το βασικό χαρακτηριστικό του LinearLayout που καθορίζει την κατεύθυνση τοποθέτησης των θυγατρικών στοιχείων. android:orientation="vertical" τακτοποιεί τα στοιχεία από πάνω προς τα κάτω· android:orientation="horizontal" — από αριστερά προς τα δεξιά (ή από δεξιά προς τα αριστερά σε RTL τοπικοποίηση). Αν δεν οριστεί προσανατολισμός, από προεπιλογή χρησιμοποιείται HORIZONTAL (σε παλαιότερες εκδόσεις) — αλλά η ρητή δήλωση είναι υποχρεωτική για προβλέψιμη συμπεριφορά.

android:gravity — στοίχιση περιεχομένου μέσα στο LinearLayout. Δέχεται συνδυασμούς: top, bottom, left, right, center, center_horizontal, center_vertical, fill, clip_vertical, clip_horizontal. Η τιμή gravity="center" για διάταξη VERTICAL θα τοποθετήσει όλα τα στοιχεία στο κέντρο οριζόντια. android:layout_gravity — χαρακτηριστικό θυγατρικού στοιχείου που το στοιχίζει μέσα στο γονικό LinearLayout. Παράδειγμα: ένα κουμπί με layout_gravity="right" σε διάταξη VERTICAL θα πιεστεί στη δεξιά άκρη.

Διαφορά: gravity — ιδιότητα του γονέα (πώς τοποθετούνται τα παιδιά μέσα του), layout_gravity — ιδιότητα του παιδιού (πώς συμπεριφέρεται μέσα στον γονέα). Το λάθος της σύγχυσης αυτών των χαρακτηριστικών είναι ένα από τα πιο συνηθισμένα στους αρχάριους.

Baseline alignment

Για διατάξεις HORIZONTAL με στοιχεία κειμένου (TextView, Button, EditText) είναι χρήσιμο το android:baselineAligned="true" — στοιχίζει όλα τα κείμενα στη γραμμή βάσης της γραμματοσειράς, ανεξάρτητα από το padding, size ή height τους. Αυτό κάνει μια γραμμή με εικονίδιο, τίτλο και περιγραφή οπτικά τακτοποιημένη: το κείμενο δεν πηδά πάνω-κάτω.

layout_weight: κατανομή βάρους

layout_weight — χαρακτηριστικό θυγατρικού στοιχείου του LinearLayout που καθορίζει ποιο μέρος του ελεύθερου χώρου θα καταλάβει. Λειτουργεί μόνο στην κατεύθυνση του προσανατολισμού (πλάτος για HORIZONTAL, ύψος για VERTICAL). Τύπος υπολογισμού: μέγεθος = δικό του μέγεθος + (ελεύθερος χώρος × (βάρος στοιχείου / άθροισμα όλων των βαρών)). Ελεύθερος χώρος = μέγεθος γονέα — άθροισμα όλων των δικών μεγεθών των παιδιών.

Το layout_weight είναι πιο αποτελεσματικό από τα σταθερά μεγέθη για προσαρμοστικές διεπαφές. Για παράδειγμα, αν ο αριστερός πίνακας πρέπει να καταλαμβάνει το 30% της οθόνης και ο δεξιός — 70%, ορίστε weight=3 και weight=7. Για σωστή λειτουργία, συνήθως το μέγεθος στην κατεύθυνση ορίζεται σε 0dp (android:layout_width="0dp" για HORIZONTAL), τότε το δικό του μέγεθος του στοιχείου θεωρείται μηδέν και ολόκληρο το μέγεθος καθορίζεται μόνο από το weight. Αυτή είναι η τυπική σύσταση της Google (Android Developers Guide, 2024).

Σημαντικό: τα βάρη αθροίζονται για όλα τα στοιχεία στο LinearLayout, συμπεριλαμβανομένων εκείνων χωρίς weight (το βάρος τους θεωρείται 0). Αν ένα στοιχείο έχει weight=1 και ένα άλλο weight=2, το πρώτο θα καταλάβει 1/3 του ελεύθερου χώρου, το δεύτερο — 2/3. Το weightSum (χαρακτηριστικό γονέα) επιτρέπει τον ορισμό μέγιστου αθροίσματος βάρους — αν τα βάρη των παιδιών συνολικά είναι μικρότερα από weightSum, η διαφορά παραμένει ως κενός χώρος.

Παραδείγματα κώδικα: διατάξεις XML

Παράδειγμα 1: Κάθετη φόρμα με weight

Η φόρμα σύνδεσης αποτελείται από τρία στοιχεία: πεδίο email (καταλαμβάνει 2/4), πεδίο κωδικού (1/4) και κουμπί (1/4) του ύψους οθόνης. Και τα τρία στοιχεία με weight λειτουργούν μόνο στον προσανατολισμό VERTICAL κατά ύψος.

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="Κωδικός"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/login_button"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="Σύνδεση" />

</LinearLayout>

Ύψος κάθε στοιχείου = (parent_height — padding) × (weight / sumWeights). Το email θα λάβει 2/4 του ύψους, ο κωδικός και το κουμπί — από 1/4. Όλα height=0dp, επομένως το δικό τους μέγεθος δεν λαμβάνεται υπόψη — λειτουργεί μόνο το weight.

Παράδειγμα 2: Οριζόντια γραμμή εργαλείων

Πίνακας με τρία κουμπιά: εικονίδιο πίσω (wrap_content), τίτλος (γεμίζει το υπόλοιπο) και εικονίδιο μενού (wrap_content). weight για τίτλο = 1, κουμπιά χωρίς 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="Τίτλος"
        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>

Τα κουμπιά πίσω και μενού καταλαμβάνουν ακριβώς όσο χρειάζεται για το εικονίδιο. Ο τίτλος (TextView) με width=0dp και weight=1 τεντώνεται σε όλο τον υπόλοιπο χώρο μεταξύ τους. gravity="center_vertical" στοιχίζει όλα τα στοιχεία στο κάθετο κέντρο.

Παράδειγμα 3: Ένθετα LinearLayout για σύνθετη κάρτα

Κάρτα προϊόντος: οριζόντια γραμμή (εικόνα + κάθετο μπλοκ κειμένου). Εξωτερικό LinearLayout HORIZONTAL, εσωτερικό — VERTICAL για τίτλο, περιγραφή και τιμή.

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="Όνομα προϊόντος"
            android:textStyle="bold"
            android:textSize="16sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Σύντομη περιγραφή προϊόντος σε δύο γραμμές"
            android:textSize="14sp"
            android:textColor="@color/gray" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="1 299 τρίψιμο."
            android:textSize="18sp"
            android:textColor="@color/accent" />

    </LinearLayout>

</LinearLayout>

Εικόνα αριστερά (80×80dp), δεξιά — κάθετο μπλοκ τριών γραμμών κειμένου. Το εσωτερικό LinearLayout έχει weight=1, επομένως καταλαμβάνει όλο τον υπόλοιπο χώρο μετά την εικόνα. Αυτό είναι ένα κλασικό μοτίβο κάρτας λίστας που συναντάται σε χιλιάδες εφαρμογές.

Πρόβλημα ένθεσης και εναλλακτικές

Το κύριο μειονέκτημα του LinearLayout — η ανάγκη για ένθετα δοχεία σε σύνθετες διατάξεις. Αν χρειαστεί να τοποθετήσετε στοιχεία σε ένα πλέγμα 2×2 ή να κάνετε μια γραμμή με στοίχιση σε δύο άκρες, απαιτούνται τουλάχιστον 2–3 επίπεδα ένθεσης. Κάθε επίπεδο LinearLayout προσθέτει 2 περάσματα onMeasure, που σε αδύναμες συσκευές οδηγεί σε αισθητή καθυστέρηση κατά την απόδοση.

Σύμφωνα με το Android Performance Blog (Google, 2017), κάθε επιπλέον επίπεδο ένθεσης αυξάνει τον χρόνο διάταξης κατά 30–50 μs. Για μια λίστα 20 στοιχείων με 3 επίπεδα ένθεσης, η καθυστέρηση μπορεί να φτάσει τα 3 ms ανά στοιχείο — αυτό είναι αισθητό jank κατά την κύλιση. Το ConstraintLayout λύνει αυτό το πρόβλημα μέσω επίπεδης ιεραρχίας, αντικαθιστώντας 3–4 ένθετα LinearLayout με ένα δοχείο με περιορισμούς.

Σύσταση: χρησιμοποιήστε LinearLayout για απλές γραμμικές διατάξεις (έως 10 στοιχεία, ένα επίπεδο ένθεσης). Για κάρτες λίστας, φόρμες με διαφορετική στοίχιση και οθόνες με δομή πίνακα, επιλέξτε ConstraintLayout. Για επαναλαμβανόμενα στοιχεία στο RecyclerView, χρησιμοποιήστε ConstraintLayout στο αρχείο διάταξης του στοιχείου — αυτό είναι κρίσιμο για την απόδοση κύλισης.

Συχνές ερωτήσεις

Γιατί δεν λειτουργεί το layout_weight;

Η συνηθέστερη αιτία — το μέγεθος στην κατεύθυνση δεν έχει οριστεί σε 0dp. Για διάταξη HORIZONTAL χρειάζεται android:layout_width="0dp", για VERTICAL — android:layout_height="0dp". Αν το στοιχείο έχει wrap_content ή match_parent, το weight μπορεί να μην λειτουργήσει ή να δώσει απροσδόκητο αποτέλεσμα. Δεύτερη αιτία — το weightSum στον γονέα είναι μικρότερο από το άθροισμα weight των παιδιών. Τρίτη — χρήση match_parent σε θυγατρικό στοιχείο στην αντίθετη κατεύθυνση.

Ποια είναι η διαφορά μεταξύ layout_weight και weightSum;

layout_weight ορίζεται σε κάθε θυγατρικό στοιχείο και καθορίζει το μερίδιό του στον ελεύθερο χώρο. weightSum — χαρακτηριστικό του γονέα LinearLayout που ορίζει το μέγιστο άθροισμα βαρών. Από προεπιλογή, weightSum = άθροισμα όλων των layout_weight των παιδιών. Αν ορίσετε weightSum = 3 και παιδιά με weight=1, το καθένα θα καταλάβει 1/3. Αν υπάρχουν μόνο δύο παιδιά με weight=1, το υπόλοιπο 1/3 θα είναι κενό. Το weightSum είναι βολικό για καθορισμό αναλογιών χωρίς επανυπολογισμό κατά την προσθήκη/αφαίρεση στοιχείων.

Πώς αφαιρώ τα κενά μεταξύ των στοιχείων του LinearLayout;

Από προεπιλογή δεν υπάρχουν κενά — τα στοιχεία τοποθετούνται το ένα δίπλα στο άλλο. Αν εμφανίστηκαν κενά, ελέγξτε: android:divider και android:showDividers στον γονέα, android:layout_margin στα θυγατρικά στοιχεία. Επιπλέον μπορεί να επηρεάσει το android:weightSum — αν τα στοιχεία χρησιμοποιούν weight, μπορεί να μείνει κενός χώρος μεταξύ τους λόγω λανθασμένου υπολογισμού. Για μηδενικά κενά, ορίστε σε όλα τα παιδιά margin=0dp και αφαιρέστε το divider.

Ποιο είναι ταχύτερο: LinearLayout ή ConstraintLayout;

Για απλές μονής κατεύθυνσης διατάξεις (1–5 στοιχεία σε γραμμή/στήλη) το LinearLayout είναι ελαφρώς ταχύτερο — δεν ξοδεύει πόρους για τον υπολογισμό περιορισμών. Για σύνθετες διατάξεις (πάνω από 5 στοιχεία, πλέγματα, διαφορετικούς τύπους στοίχισης) το ConstraintLayout είναι ταχύτερο επειδή χρησιμοποιεί επίπεδη ιεραρχία αντί για ένθετα LinearLayout. Σύμφωνα με δοκιμές της Google (Android Performance Blog), το ConstraintLayout κερδίζει σε διατάξεις που απαιτούν 3+ επίπεδα ένθεσης LinearLayout.

Σύνοψη

  • LinearLayout — βασική ViewGroup Android για διαδοχική τοποθέτηση στοιχείων κάθετα ή οριζόντια.
  • Προσανατολισμός — android:orientation="vertical" (στήλη) ή "horizontal" (γραμμή) καθορίζει την κατεύθυνση διάταξης.
  • layout_weight — μηχανισμός κατανομής ελεύθερου χώρου ανάλογα με το βάρος στοιχείων με μεγέθη 0dp.
  • Gravity — android:gravity (στοίχιση παιδιών μέσα στον γονέα) vs android:layout_gravity (στοίχιση παιδιού στον γονέα).
  • Ένθεση — κύριο μειονέκτημα: για σύνθετες διατάξεις απαιτούνται 2–3 επίπεδα, που επιβραδύνει την απόδοση κατά 30–50 μs ανά επίπεδο.
  • Επιλογή — LinearLayout για απλές γραμμές/στήλες (έως 10 στοιχεία), ConstraintLayout για σύνθετες διατάξεις.
  • Προσαρμοστικότητα — ο συνδυασμός weight + 0dp + baseline alignment καλύπτει το 80% των εργασιών γραμμικής διάταξης.

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης