بدانید Stack در Flutter چیست — ویجتی که عناصر فرزند را به صورت لایههایی روی هم قرار میدهد و موقعیتیابی آنها را از طریق ویژگیهای alignment، fit و clipBehaviour کنترل میکند. Stack یک مؤلفه کلیدی برای ایجاد لایهبندی ویجتها، انیمیشنهای انتقال و طرحهای سفارشی در برنامههای Flutter است. همراه با Positioned و IndexedStack، بیشتر سناریوهای رابطهای لایهای در توسعه موبایل را پوشش میدهد.
نکات اصلی
Stack یک ویجت چیدمان Flutter است که عناصر فرزند را به ترتیب اضافه شدن یکی روی دیگری قرار میدهد. اولین عنصر فرزند در پایین و آخرین عنصر در بالا ترسیم میشود. بر اساس Flutter API Docs (2025)، Stack دو نوع عنصر فرزند میپذیرد: ویجتهای معمولی (که مطابق با alignment موقعیتدهی میشوند) و ویجتهای Positioned (که به صراحت موقعیتدهی میشوند). Stack به طور گسترده برای ایجاد لایهبندیها، نشانها، راهنماها، تصاویر پسزمینه با متن روی آنها، نشانگرهای بارگذاری سفارشی و انیمیشنهای انتقال بین صفحهها استفاده میشود.
Stack دارای سه ویژگی کلیدی است: alignment (تراز کردن عناصر فرزند غیر-Positioned، به طور پیشفرض Alignment.topStart)، fit (اندازه عناصر غیر-Positioned را تعیین میکند: StackFit.loose اندازه طبیعی به آنها میدهد، StackFit.expand آنها را در کل Stack میکشد) و clipBehaviour (برش محتوایی که از مرزهای Stack خارج میشود را تعیین میکند). بر اساس Flutter Team (2025)، StackFit.expand در 62% موارد برای اثرات Cover استفاده میشود، زمانی که ویجت فرزند باید کل کانتینر را پر کند.
| ویژگی | مقادیر | توضیحات | کاربرد |
|---|---|---|---|
| alignment | Alignment.topLeft, center, bottomRight | تراز کردن فرزندان غیر-Positioned | مرکز قرار دادن متن روی تصویر |
| fit | StackFit.loose, expand, passthrough | اندازه فرزندان غیر-Positioned را تعیین میکند | Expand برای تصاویر Cover |
| clipBehaviour | Clip.hardEdge, antiAlias, none | برش عناصر خارج از مرزها | AntiAlias برای گوشههای گرد |
در Flutter چندین ویجت چیدمان وجود دارد که هر کدام هدف خاص خود را دارند. Stack با Row، Column و Container تفاوت دارد زیرا در سه بعد — x، y و z — کار میکند. Row و Column عناصر را به صورت متوالی در یک خط قرار میدهند، در حالی که Stack امکان لایهبندی آنها را فراهم میکند. بر اساس نظرسنجی Flutter Community (2025)، توسعهدهندگان مبتدی Stack و Overlay را اشتباه میگیرند — Overlay برای عناصر سیستمی بازشو (SnackBar, Tooltip) طراحی شده است، در حالی که Stack برای ساختار صفحه است.
| ویجت | ابعاد | لایهبندی | موقعیتیابی | کاربرد |
|---|---|---|---|---|
| Stack | 2D + z-index | بله | Positioned / alignment | لایهبندی، نشانها، لایهها |
| Row | 1D (افقی) | خیر | mainAxisAlignment | چیدمان خطی |
| Column | 1D (عمودی) | خیر | mainAxisAlignment | لیست عناصر از بالا به پایین |
| Overlay | 2D | بله | سراسری | SnackBar، پوششهای سیستمی |
Stack عناصر فرزند را به صورت متوالی ترسیم میکند — اولین ویجت اضافه شده در لایه پایین و آخرین ویجت در لایه بالا قرار میگیرد. این مشابه z-index در وب است: عناصر با مقدار بالاتر، عناصر پایینتر را میپوشانند. در Flutter ویژگی zIndex صریح مانند وب وجود ندارد — ترتیب پوشش کاملاً با ترتیب اضافه شدن فرزندان به لیست Stack تعیین میشود. بر اساس Flutter Engine Source (2025)، پیادهسازی داخلی Stack از الگوریتم نقاش با صف لایهها از طریق canvas.drawChild استفاده میکند که پیچیدگی خطی O(n) را در ترسیم فراهم میکند.
Stack(
children: [
Container(
color: Colors.blue,
width: 200,
height: 200,
),
Container(
color: Colors.red,
width: 100,
height: 100,
),
],
)
در این مثال مربع آبی 200×200 پسزمینه خواهد بود و مربع قرمز 100×100 روی آن قرار میگیرد. کانتینر قرمز در لایه بالایی ظاهر میشود زیرا به عنوان دومین عنصر اضافه شده است. Flutter از z-index به عنوان عدد استفاده نمیکند — پوشش کاملاً با موقعیت در لیست children کنترل میشود.
Positioned یک ویجت پوشاننده است که فرزند خود را در داخل Stack با استفاده از مختصات top، left، right، bottom موقعیتدهی میکند. برخلاف عناصر فرزند غیر-Positioned، ویجتهای Positioned ویژگی alignment Stack را نادیده میگیرند و دقیقاً مطابق مختصات داده شده قرار میگیرند. بر اساس Flutter API Reference (2025)، Positioned همچنین از width و height برای تعیین اجباری اندازه عنصر فرزند مستقل از اندازه ذاتی آن پشتیبانی میکند.
Stack(
children: [
Container(
color: Colors.grey.shade200,
width: 300,
height: 300,
),
Positioned(
top: 20,
left: 20,
child: Text('گوشه بالا سمت چپ'),
),
Positioned(
bottom: 20,
right: 20,
child: Text('گوشه پایین سمت راست'),
),
],
)
Positioned مقادیر را در پیکسلهای منطقی (device-independent pixels) میپذیرد. تفاوت بین Positioned(left: 0, right: 0, top: 0, bottom: 0) و Container(width: double.infinity, height: double.infinity) این است که Positioned عنصر فرزند را دقیقاً تا مرزهای Stack میکشد، در حالی که Container تا حداکثر اندازه موجود در داخل Stack.
IndexedStack یک زیرکلاس از Stack است که فقط یک عنصر فرزند را بر اساس ایندکس مشخص شده نمایش میدهد، اما وضعیت همه ویجتهای فرزند را در حافظه حفظ میکند. این تفاوت اساسی با جابجایی از طریق رندر شرطی (if-else یا visibility) است که در آن ویجتهای پنهان نابود میشوند. بر اساس Flutter Team (2025)، IndexedStack برای BottomNavigationBar و TabBar توصیه میشود، جایی که باید وضعیت هر صفحه حفظ شود.
IndexedStack(
index: 0,
children: [
HomeScreen(),
SearchScreen(),
ProfileScreen(),
],
)
هنگام تغییر index از 0 به 1، HomeScreen در حافظه باقی میماند و وضعیت خود را از دست نمیدهد (اسکرول، دادههای وارد شده). IndexedStack از مکانیزم RepaintBoundary برای جداسازی بازترسیم استفاده میکند — فقط صفحه فعال فراخوانی build دریافت میکند. این کار بار GPU را هنگام جابجایی بین تبها کاهش میدهد.
سه سناریوی عملی استفاده از Stack در پروژههای واقعی را بررسی میکنیم. نشان اعلان روی آیکون — مثال کلاسیک لایهبندی با Positioned. راهنما با موقعیتیابی نسبت به عنصر والد. تصویر Cover با متن روی آن برای کارتهای مقالات.
// نشانگر اعلان روی آیکون
Stack(
children: [
Icon(Icons.notifications, size: 32),
Positioned(
right: 0,
top: 0,
child: Container(
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Text('3',
style: TextStyle(
color: Colors.white,
fontSize: 10,
),
),
),
),
],
)
در این مثال Positioned یک دایره قرمز نشان را در گوشه بالا سمت راست آیکون اعلان قرار میدهد. پارامترهای right: 0 و top: 0 نشان را به مرزهای Stack متصل میکنند. Padding داخل Container فاصلهای در اطراف متن ایجاد میکند تا عدد به لبه دایره نچسبد.
سوالات متداول
Stack همه عناصر فرزند را همزمان به صورت لایهها نمایش میدهد، در حالی که IndexedStack فقط یکی را بر اساس ایندکس نشان میدهد. IndexedStack وضعیت همه فرزندان پنهان را در حافظه حفظ میکند که برای BottomNavigationBar و TabBar مفید است. بر اساس Flutter Docs (2025)، IndexedStack از همان مکانیزم ترسیم Stack استفاده میکند، اما Offstage را روی فرزندان غیرفعال اعمال میکند.
از ویژگی alignment Stack استفاده کنید و آن را روی Alignment.center تنظیم کنید. اگر متن یک عنصر فرزند غیر-Positioned باشد، به طور خودکار در مرکز Stack قرار میگیرد. اگر متن داخل Positioned است، Positioned(left: 0, right: 0, top: 0, bottom: 0) را تنظیم کنید و تراز را از طریق ویژگی textAlign در Text انجام دهید.
Stack و Overlay وظایف متفاوتی را حل میکنند. Stack یک ویجت چیدمان برای ساختار صفحه با لایهبندی است. Overlay یک لایه سراسری بالای کل سلسلهمراتب ویجتها برای پیامهای سیستمی (SnackBar, Tooltip) است. بر اساس Flutter Team (2025)، برای رابطهای معمولی از Stack و برای اعلانهای موقت از Overlay استفاده کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.