LinearLayout: kiến thức cơ bản, hướng và phân bổ trọng lượng trong Android

Tác giả: IT Sectr Đã đăng: 2026-02-24 Thời gian đọc: 9 phút

Giải thích kiến thức cơ bản về LinearLayout — một ViewGroup cơ bản trong Android SDK để căn chỉnh các phần tử con trên một dòng: theo chiều dọc (LinearLayout.VERTICAL) hoặc chiều ngang (LinearLayout.HORIZONTAL). LinearLayout vẫn là cách đơn giản và nhanh nhất để xây dựng một hàng nút, danh sách cài đặt hoặc biểu mẫu nhập liệu khi độ phức tạp của bố cục không vượt quá 5–10 phần tử. Các thuộc tính layout_weightorientation quản lý việc phân phối không gian và hướng. Thông số kỹ thuật chi tiết — trong LinearLayout API Reference.

Những điểm chính

  • Hướng — LinearLayout sắp xếp các phần tử tuần tự theo chiều dọc (VERTICAL) hoặc chiều ngang (HORIZONTAL), được thiết lập qua android:orientation.
  • layout_weight — phân phối không gian trống tỷ lệ thuận với trọng lượng của các phần tử; tổng trọng lượng xác định phần của mỗi phần tử.
  • gravity vs layout_gravity — android:gravity căn chỉnh nội dung bên trong LinearLayout; android:layout_gravity căn chỉnh chính phần tử bên trong phần tử cha.
  • Lồng nhau — nhược điểm chính: lưới phức tạp yêu cầu lồng nhiều LinearLayout, làm giảm hiệu suất.
  • Căn chỉnh đường cơ sở — căn chỉnh các phần tử văn bản theo đường cơ sở của phông chữ bất kể padding và chiều cao phần tử.

LinearLayout là gì?

LinearLayout — một trong những ViewGroup đầu tiên trong Android SDK (API Level 1), được thiết kế để sắp xếp các phần tử con tuần tự trong một hàng hoặc cột duy nhất. Mỗi phần tử mới được đặt sau phần tử trước đó và hướng được thiết lập bởi thuộc tính android:orientation. LinearLayout là vùng chứa Android đơn giản và dễ dự đoán nhất, khiến nó trở thành lựa chọn lý tưởng cho các giao diện tuyến tính: hàng nút, danh sách cài đặt với biểu tượng và văn bản, menu ngang.

Về mặt lịch sử, LinearLayout là ViewGroup đầu tiên mà một nhà phát triển Android mới bắt đầu làm quen. Ưu điểm của nó là tính minh bạch: các phần tử con được đặt chính xác theo thứ tự khai báo, không có quy tắc định vị ẩn. Không giống như RelativeLayout, nơi một phần tử có thể được gắn vào bất kỳ phần tử lân cận nào, hoặc ConstraintLayout với hệ thống ràng buộc của nó, LinearLayout hoạt động theo nguyên tắc "đầu tiên bên trái/trên, thứ hai sau nó, thứ ba sau thứ hai". Theo Google I/O 2017, 78% màn hình trong top 1000 ứng dụng Google Play sử dụng LinearLayout làm vùng chứa chính hoặc phụ trợ.

Số liệu chính của LinearLayout là LinearLayout.MeasureSpec — hệ thống quản lý kích thước. Với hướng VERTICAL, chiều rộng của mỗi phần tử bằng chiều rộng của phần tử cha (match_parent hoặc cố định) và chiều cao được xác định bởi nội dung hoặc thuộc tính. Đối với HORIZONTAL thì ngược lại: chiều cao bằng của phần tử cha, chiều rộng theo nội dung. Nếu trong một hàng HORIZONTAL, tổng chiều rộng của các phần tử vượt quá chiều rộng của phần tử cha, các phần tử có thể tràn ra ngoài màn hình (nếu không sử dụng weight).

Cấu trúc bên trong

LinearLayout ghi đè onMeasure và onLayout từ ViewGroup. Với hướng VERTICAL, onLayout đặt các phần tử dọc theo trục Y: phần tử con đầu tiên — y=0, thứ hai — y=prev.bottom + divider.hidden, v.v. Với HORIZONTAL — dọc theo trục X. Dấu phân cách được thiết lập qua android:divider và android:showDividers (beginning, middle, end). Dấu phân cách có thể là màu sắc, drawable hoặc tài nguyên Shape tùy chỉnh.

Hướng và Gravity: VERTICAL và HORIZONTAL

Hướng — một thuộc tính chính của LinearLayout xác định hướng sắp xếp các phần tử con. android:orientation="vertical" sắp xếp các phần tử từ trên xuống dưới; android:orientation="horizontal" — từ trái sang phải (hoặc từ phải sang trái với bản địa hóa RTL). Nếu hướng không được thiết lập, HORIZONTAL được sử dụng theo mặc định (trên các phiên bản cũ) — nhưng chỉ định rõ ràng là cần thiết để có hành vi có thể dự đoán được.

android:gravity — căn chỉnh nội dung bên trong LinearLayout. Chấp nhận các kết hợp: top, bottom, left, right, center, center_horizontal, center_vertical, fill, clip_vertical, clip_horizontal. Giá trị gravity="center" cho bố cục VERTICAL sẽ căn giữa tất cả các phần tử theo chiều ngang. android:layout_gravity — một thuộc tính của phần tử con căn chỉnh nó bên trong LinearLayout cha. Ví dụ: một nút có layout_gravity="right" trong bố cục VERTICAL sẽ đẩy nút về cạnh phải.

Sự khác biệt: gravity — thuộc tính của cha (cách các phần tử con được sắp xếp bên trong nó), layout_gravity — thuộc tính của con (cách nó hoạt động bên trong cha). Nhầm lẫn các thuộc tính này là một trong những lỗi phổ biến nhất ở người mới bắt đầu.

Căn chỉnh đường cơ sở

Đối với bố cục HORIZONTAL có các phần tử văn bản (TextView, Button, EditText), android:baselineAligned="true" rất hữu ích — nó căn chỉnh tất cả văn bản theo đường cơ sở của phông chữ, bất kể padding, kích thước hoặc chiều cao của chúng. Điều này làm cho một hàng có biểu tượng, tiêu đề và mô tả trở nên gọn gàng về mặt thị giác: văn bản không nhảy lên xuống.

layout_weight: Phân bổ trọng lượng

layout_weight — một thuộc tính của phần tử con của LinearLayout xác định phần không gian trống mà nó sẽ chiếm. Nó chỉ hoạt động theo hướng của hướng (chiều rộng cho HORIZONTAL, chiều cao cho VERTICAL). Công thức tính: kích thước = kích thước riêng + (không gian trống × (trọng lượng phần tử / tổng tất cả trọng lượng)). Không gian trống = kích thước cha — tổng tất cả kích thước riêng của các phần tử con.

layout_weight hiệu quả hơn so với kích thước cố định cho các giao diện thích ứng. Ví dụ: nếu bảng điều khiển bên trái chiếm 30% màn hình và bên phải 70%, hãy đặt weight=3 và weight=7. Để hoạt động chính xác, kích thước theo hướng thường được đặt thành 0dp (android:layout_width="0dp" cho HORIZONTAL), khi đó kích thước riêng của phần tử được coi là không và toàn bộ kích thước chỉ được xác định bởi weight. Đây là khuyến nghị tiêu chuẩn của Google (Android Developers Guide, 2024).

Quan trọng: trọng lượng được tính tổng cho tất cả các phần tử trong LinearLayout, bao gồm cả những phần tử không có weight được đặt (trọng lượng của chúng được coi là 0). Nếu một phần tử có weight=1 và phần tử khác có weight=2, phần tử đầu tiên sẽ chiếm 1/3 không gian trống, phần tử thứ hai — 2/3. weightSum (một thuộc tính của cha) cho phép đặt tổng trọng lượng tối đa — nếu tổng trọng lượng của các phần tử con nhỏ hơn weightSum, phần chênh lệch sẽ là không gian trống.

Ví dụ mã: Bố cục XML

Ví dụ 1: Biểu mẫu dọc với weight

Biểu mẫu đăng nhập bao gồm ba phần tử: trường email (chiếm 2/4 chiều cao màn hình), trường mật khẩu (1/4) và nút (1/4). Cả ba phần tử có weight chỉ hoạt động theo hướng VERTICAL theo chiều cao.

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="Mật khẩu"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/login_button"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="Đăng nhập" />

</LinearLayout>

Chiều cao của mỗi phần tử = (parent_height — padding) × (weight / sumWeights). email nhận 2/4 chiều cao, mật khẩu và nút — mỗi cái 1/4. Tất cả height=0dp, do đó kích thước riêng không được xem xét — chỉ weight hoạt động.

Ví dụ 2: Thanh công cụ ngang

Một bảng điều khiển với ba nút: biểu tượng quay lại (wrap_content), tiêu đề (điền phần còn lại) và biểu tượng menu (wrap_content). weight cho tiêu đề = 1, các nút không có 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="Tiêu đề"
        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>

Các nút quay lại và menu chiếm chính xác không gian cần thiết cho biểu tượng. Tiêu đề (TextView) với width=0dp và weight=1 mở rộng ra toàn bộ không gian còn lại giữa chúng. gravity="center_vertical" căn giữa tất cả các phần tử theo chiều dọc.

Ví dụ 3: LinearLayout lồng nhau cho thẻ phức tạp

Một thẻ sản phẩm: hàng ngang (hình ảnh + khối văn bản dọc). LinearLayout bên ngoài HORIZONTAL, bên trong — VERTICAL cho tiêu đề, mô tả và giá.

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="Tên sản phẩm"
            android:textStyle="bold"
            android:textSize="16sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Mô tả ngắn sản phẩm trong hai dòng"
            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>

Hình ảnh bên trái (80×80dp), bên phải — một khối dọc gồm ba dòng văn bản. LinearLayout bên trong có weight=1, do đó nó chiếm tất cả không gian còn lại sau hình ảnh. Đây là mẫu thẻ danh sách cổ điển được tìm thấy trong hàng nghìn ứng dụng.

Vấn đề lồng nhau và các giải pháp thay thế

Nhược điểm chính của LinearLayout — sự cần thiết của các vùng chứa lồng nhau cho bố cục phức tạp. Nếu bạn cần sắp xếp các phần tử trong lưới 2×2 hoặc tạo một hàng có căn chỉnh ở cả hai cạnh, cần ít nhất 2–3 cấp độ lồng nhau. Mỗi cấp độ LinearLayout thêm 2 lần truyền onMeasure, trên các thiết bị yếu dẫn đến độ trễ đáng kể trong quá trình kết xuất.

Theo Android Performance Blog (Google, 2017), mỗi cấp độ lồng nhau bổ sung làm tăng thời gian bố cục thêm 30–50 μs. Đối với danh sách 20 mục với 3 cấp độ lồng nhau, độ trễ có thể đạt tới 3 ms cho mỗi phần tử — đây là hiện tượng giật (jank) đáng chú ý khi cuộn. ConstraintLayout giải quyết vấn đề này thông qua hệ thống phân cấp phẳng, thay thế 3–4 LinearLayout lồng nhau bằng một vùng chứa ràng buộc duy nhất.

Khuyến nghị: sử dụng LinearLayout cho bố cục tuyến tính đơn giản (tối đa 10 phần tử, một cấp độ lồng nhau). Đối với thẻ danh sách, biểu mẫu có căn chỉnh khác nhau và màn hình có cấu trúc bảng, hãy chọn ConstraintLayout. Đối với các phần tử lặp lại trong RecyclerView, hãy sử dụng ConstraintLayout trong tệp bố cục mục — điều này rất quan trọng cho hiệu suất cuộn.

Câu hỏi thường gặp

Tại sao layout_weight không hoạt động?

Lý do phổ biến nhất — kích thước theo hướng không được đặt thành 0dp. Đối với bố cục HORIZONTAL bạn cần android:layout_width="0dp", đối với VERTICAL — android:layout_height="0dp". Nếu phần tử có wrap_content hoặc match_parent, weight có thể không hoạt động hoặc cho kết quả không mong muốn. Lý do thứ hai — weightSum trên cha nhỏ hơn tổng trọng lượng của các phần tử con. Lý do thứ ba — sử dụng match_parent trên phần tử con theo hướng ngược lại.

Sự khác biệt giữa layout_weight và weightSum là gì?

layout_weight được đặt trên mỗi phần tử con và xác định phần của nó trong không gian trống. weightSum — một thuộc tính của LinearLayout cha đặt tổng trọng lượng tối đa. Theo mặc định, weightSum = tổng tất cả layout_weight của các phần tử con. Nếu bạn đặt weightSum = 3 và các phần tử con có weight=1, mỗi phần tử sẽ chiếm 1/3. Nếu chỉ có hai phần tử con với weight=1, 1/3 còn lại sẽ trống. weightSum thuận tiện để cố định tỷ lệ mà không cần tính toán lại khi thêm/xóa phần tử.

Làm cách nào để loại bỏ khoảng cách giữa các phần tử LinearLayout?

Theo mặc định không có khoảng cách — các phần tử được đặt liền kề nhau. Nếu khoảng cách xuất hiện, hãy kiểm tra: android:dividerandroid:showDividers trên cha, android:layout_margin trên các phần tử con. Ngoài ra, android:weightSum có thể ảnh hưởng — nếu các phần tử sử dụng weight, có thể còn khoảng trống giữa chúng do tính toán không chính xác. Để không có khoảng cách, đặt tất cả lề của phần tử con thành 0dp và loại bỏ dấu phân cách.

Cái nào nhanh hơn: LinearLayout hay ConstraintLayout?

Đối với bố cục đơn hướng đơn giản (1–5 phần tử trong một hàng/cột) LinearLayout nhanh hơn một chút — nó không tốn tài nguyên cho việc tính toán ràng buộc. Đối với bố cục phức tạp (hơn 5 phần tử, lưới, các loại căn chỉnh khác nhau) ConstraintLayout nhanh hơn vì nó sử dụng hệ thống phân cấp phẳng thay vì LinearLayout lồng nhau. Theo các thử nghiệm của Google (Android Performance Blog), ConstraintLayout chiến thắng trên các bố cục yêu cầu 3+ cấp độ lồng nhau LinearLayout.

Tóm tắt

  • LinearLayout — một ViewGroup Android cơ bản để sắp xếp tuần tự các phần tử theo chiều dọc hoặc chiều ngang.
  • Hướng — android:orientation="vertical" (cột) hoặc "horizontal" (hàng) xác định hướng bố cục.
  • layout_weight — cơ chế phân phối không gian trống tỷ lệ thuận với trọng lượng của các phần tử với kích thước được đặt thành 0dp.
  • Gravity — android:gravity (căn chỉnh các phần tử con bên trong cha) vs android:layout_gravity (căn chỉnh phần tử con trong cha).
  • Lồng nhau — nhược điểm chính: bố cục phức tạp cần 2–3 cấp độ, làm chậm kết xuất 30–50 μs mỗi cấp độ.
  • Lựa chọn — LinearLayout cho hàng/cột đơn giản (tối đa 10 phần tử), ConstraintLayout cho bố cục phức tạp.
  • Khả năng thích ứng — sự kết hợp weight + 0dp + baseline alignment bao phủ 80% tác vụ bố cục tuyến tính.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm