مبانی LinearLayout را توضیح میدهیم — ViewGroup پایه در Android SDK برای تراز کردن عناصر فرزند در یک خط: به صورت عمودی (LinearLayout.VERTICAL) یا افقی (LinearLayout.HORIZONTAL). LinearLayout سادهترین و سریعترین راه برای ساخت یک ردیف دکمه، لیست تنظیمات یا فرم ورود باقی میماند، زمانی که پیچیدگی طرح از ۵–۱۰ عنصر تجاوز نمیکند. ویژگیهای layout_weight و orientation توزیع فضا و جهت را کنترل میکنند. مشخصات دقیق — در LinearLayout API Reference.
نکات اصلی
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 سفارشی باشد.
جهتگیری — ویژگی کلیدی 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 — ویژگی فرزند (رفتار آن در داخل والد). اشتباه گرفتن این ویژگیها یکی از رایجترین خطاها در میان مبتدیان است.
برای طرحهای HORIZONTAL با عناصر متنی (TextView, Button, EditText) android:baselineAligned="true" مفید است — همه متنها را بر اساس خط پایه فونت تراز میکند، صرف نظر از padding، size یا height آنها. این باعث میشود ردیف با آیکون، عنوان و توضیحات از نظر بصری مرتب به نظر برسد: متن بالا و پایین نمیپرد.
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 باشد، تفاوت به عنوان فضای خالی باقی میماند.
فرم ورود از سه عنصر تشکیل شده است: فیلد ایمیل (۲/۴ را میگیرد)، فیلد رمز عبور (۴/۱) و دکمه (۴/۱) از ارتفاع صفحه. هر سه عنصر با weight فقط در جهت VERTICAL بر اساس ارتفاع کار میکنند.
<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.
<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 بیرونی HORIZONTAL، داخلی — VERTICAL برای عنوان، توضیحات و قیمت.
<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 عنصر استفاده کنید — این برای عملکرد اسکرول حیاتی است.
سوالات متداول
شایعترین دلیل — اندازه در جهت روی 0dp تنظیم نشده است. برای طرح HORIZONTAL نیاز به android:layout_width="0dp" است، برای VERTICAL — android:layout_height="0dp". اگر عنصر wrap_content یا match_parent داشته باشد، weight ممکن است کار نکند یا نتیجه غیرمنتظره بدهد. دلیل دوم — weightSum در والد کمتر از مجموع weight فرزندان است. سوم — استفاده از match_parent در عنصر فرزند در جهت مخالف.
layout_weight روی هر عنصر فرزند تنظیم میشود و سهم آن را از فضای آزاد تعیین میکند. weightSum — ویژگی والد LinearLayout که حداکثر مجموع وزنها را تعیین میکند. به طور پیشفرض weightSum = مجموع layout_weight همه فرزندان است. اگر weightSum = 3 تنظیم کنید و فرزندانی با weight=1 داشته باشید، هر کدام ۳/۱ را میگیرند. اگر فقط دو فرزند با weight=1 وجود داشته باشد، ۳/۱ باقیمانده خالی خواهد بود. weightSum برای تثبیت نسبتها بدون محاسبه مجدد هنگام افزودن/حذف عناصر مناسب است.
به طور پیشفرض فاصلهای وجود ندارد — عناصر کنار هم قرار میگیرند. اگر فاصله ظاهر شده است، بررسی کنید: android:divider و android:showDividers در والد، android:layout_margin در عناصر فرزند. علاوه بر این android:weightSum ممکن است تأثیر بگذارد — اگر عناصر از weight استفاده کنند، ممکن است فضای خالی بین آنها به دلیل محاسبه نادرست باقی بماند. برای فاصله صفر، به همه فرزندان margin=0dp تنظیم کنید و divider را حذف کنید.
برای طرحهای ساده یکجهته (۱–۵ عنصر در ردیف/ستون) LinearLayout کمی سریعتر است — منابع را برای محاسبه محدودیتها مصرف نمیکند. برای طرحهای پیچیده (بیش از ۵ عنصر، شبکهها، انواع مختلف تراز) ConstraintLayout سریعتر است، زیرا از سلسلهمراتب تخت به جای LinearLayout تودرتو استفاده میکند. طبق تستهای Google (Android Performance Blog)، ConstraintLayout در طرحهایی که نیاز به ۳+ سطح تودرتوی LinearLayout دارند برنده است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید