LinearLayout: مبانی، جهت‌گیری و توزیع وزن در Android

نویسنده: IT Sectr منتشر شده: 2026-02-24 زمان مطالعه: 9 دقیقه

مبانی LinearLayout را توضیح می‌دهیم — ViewGroup پایه در Android SDK برای تراز کردن عناصر فرزند در یک خط: به صورت عمودی (LinearLayout.VERTICAL) یا افقی (LinearLayout.HORIZONTAL). LinearLayout ساده‌ترین و سریع‌ترین راه برای ساخت یک ردیف دکمه، لیست تنظیمات یا فرم ورود باقی می‌ماند، زمانی که پیچیدگی طرح از ۵–۱۰ عنصر تجاوز نمی‌کند. ویژگی‌های 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، ۷۸٪ از صفحه‌های ۱۰۰۰ برنامه برتر 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 برای رابط‌های تطبیقی کارآمدتر از اندازه‌های ثابت است. مثلاً اگر پنل چپ باید ۳۰٪ صفحه و پنل راست ۷۰٪ را بگیرد، weight=3 و weight=7 تنظیم کنید. برای کار صحیح معمولاً اندازه در جهت روی 0dp تنظیم می‌شود (android:layout_width="0dp" برای HORIZONTAL)، سپس اندازه خود عنصر صفر در نظر گرفته می‌شود و کل اندازه فقط توسط weight تعیین می‌شود. این توصیه استاندارد Google است (Android Developers Guide, 2024).

مهم: وزن‌ها برای همه عناصر در LinearLayout جمع می‌شوند، از جمله آنهایی که weight ندارند (وزن آنها ۰ محسوب می‌شود). اگر یک عنصر weight=1 و دیگری weight=2 داشته باشد، اولی ۳/۱ فضای آزاد را می‌گیرد و دومی ۳/۲. weightSum (ویژگی والد) امکان تعیین حداکثر مجموع وزن را می‌دهد — اگر مجموع وزن فرزندان کمتر از weightSum باشد، تفاوت به عنوان فضای خالی باقی می‌ماند.

نمونه کد: طرح‌های XML

مثال ۱: فرم عمودی با weight

فرم ورود از سه عنصر تشکیل شده است: فیلد ایمیل (۲/۴ را می‌گیرد)، فیلد رمز عبور (۴/۱) و دکمه (۴/۱) از ارتفاع صفحه. هر سه عنصر با 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). ایمیل ۴/۲ ارتفاع را می‌گیرد، رمز عبور و دکمه — هر کدام ۴/۱. همه height=0dp، بنابراین اندازه خود در نظر گرفته نمی‌شود — فقط weight کار می‌کند.

مثال ۲: نوار ابزار افقی

پنل با سه دکمه: آیکون بازگشت (wrap_content)، عنوان (پر کردن بقیه) و آیکون منو (wrap_content). weight برای عنوان = ۱، دکمه‌ها بدون 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" همه عناصر را در مرکز عمودی تراز می‌کند.

مثال ۳: 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="۱٬۲۹۹ روبل"
            android:textSize="18sp"
            android:textColor="@color/accent" />

    </LinearLayout>

</LinearLayout>

تصویر در چپ (۸۰×۸۰dp)، در راست — بلوک عمودی از سه خط متن. LinearLayout داخلی weight=1 دارد، بنابراین تمام فضای باقی‌مانده بعد از تصویر را می‌گیرد. این یک الگوی کلاسیک کارت لیست است که در هزاران برنامه دیده می‌شود.

مشکل تودرتو و جایگزین‌ها

عیب اصلی LinearLayout — نیاز به کانتینرهای تودرتو برای طرح‌های پیچیده. اگر نیاز به قرار دادن عناصر در یک شبکه ۲×۲ یا ساخت یک ردیف با تراز در دو لبه دارید، حداقل ۲–۳ سطح تودرتو لازم است. هر سطح LinearLayout ۲ پاس onMeasure اضافه می‌کند که در دستگاه‌های ضعیف منجر به لگ قابل توجه در هنگام رندر می‌شود.

طبق Android Performance Blog (Google, 2017)، هر سطح اضافی تودرتو زمان layout را ۳۰–۵۰ میکروثانیه افزایش می‌دهد. برای یک لیست ۲۰ عنصری با ۳ سطح تودرتو، تأخیر می‌تواند به ۳ میلی‌ثانیه در هر عنصر برسد — این یک jank قابل توجه در هنگام اسکرول است. ConstraintLayout این مشکل را از طریق سلسله‌مراتب تخت حل می‌کند و ۳–۴ LinearLayout تودرتو را با یک کانتینر دارای محدودیت جایگزین می‌کند.

توصیه: از LinearLayout برای طرح‌های خطی ساده (تا ۱۰ عنصر، یک سطح تودرتو) استفاده کنید. برای کارت‌های لیست، فرم‌های با تراز متفاوت و صفحه‌های با ساختار جدولی، ConstraintLayout را انتخاب کنید. برای عناصر تکراری در RecyclerView از ConstraintLayout در فایل layout عنصر استفاده کنید — این برای عملکرد اسکرول حیاتی است.

سوالات متداول

چرا 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 داشته باشید، هر کدام ۳/۱ را می‌گیرند. اگر فقط دو فرزند با weight=1 وجود داشته باشد، ۳/۱ باقی‌مانده خالی خواهد بود. weightSum برای تثبیت نسبت‌ها بدون محاسبه مجدد هنگام افزودن/حذف عناصر مناسب است.

چگونه فاصله بین عناصر LinearLayout را حذف کنیم؟

به طور پیش‌فرض فاصله‌ای وجود ندارد — عناصر کنار هم قرار می‌گیرند. اگر فاصله ظاهر شده است، بررسی کنید: android:divider و android:showDividers در والد، android:layout_margin در عناصر فرزند. علاوه بر این android:weightSum ممکن است تأثیر بگذارد — اگر عناصر از weight استفاده کنند، ممکن است فضای خالی بین آنها به دلیل محاسبه نادرست باقی بماند. برای فاصله صفر، به همه فرزندان margin=0dp تنظیم کنید و divider را حذف کنید.

کدام سریع‌تر است: LinearLayout یا ConstraintLayout؟

برای طرح‌های ساده یک‌جهته (۱–۵ عنصر در ردیف/ستون) LinearLayout کمی سریع‌تر است — منابع را برای محاسبه محدودیت‌ها مصرف نمی‌کند. برای طرح‌های پیچیده (بیش از ۵ عنصر، شبکه‌ها، انواع مختلف تراز) ConstraintLayout سریع‌تر است، زیرا از سلسله‌مراتب تخت به جای LinearLayout تودرتو استفاده می‌کند. طبق تست‌های Google (Android Performance Blog)، ConstraintLayout در طرح‌هایی که نیاز به ۳+ سطح تودرتوی LinearLayout دارند برنده است.

خلاصه

  • LinearLayout — ViewGroup پایه Android برای قرار دادن متوالی عناصر به صورت عمودی یا افقی.
  • جهت‌گیری — android:orientation="vertical" (ستون) یا "horizontal" (ردیف) جهت چیدمان را تعیین می‌کند.
  • layout_weight — مکانیسم توزیع فضای آزاد به نسبت وزن عناصر با اندازه‌های 0dp.
  • Gravity — android:gravity (تراز فرزندان داخل والد) vs android:layout_gravity (تراز فرزند در والد).
  • تودرتو — عیب اصلی: برای طرح‌های پیچیده ۲–۳ سطح لازم است که رندر را ۳۰–۵۰ میکروثانیه در هر سطح کند می‌کند.
  • انتخاب — LinearLayout برای ردیف/ستون‌های ساده (تا ۱۰ عنصر)، ConstraintLayout برای طرح‌های پیچیده.
  • تطبیق‌پذیری — ترکیب weight + 0dp + baseline alignment ۸۰٪ از وظایف چیدمان خطی را پوشش می‌دهد.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید