Flexible — ویجت Flutter که نحوه اشغال فضای موجود توسط عنصر فرزند در کانتینر Flex را مدیریت میکند. برخلاف Expanded، Flexible فرزند را مجبور به پر کردن کل منطقه اختصاصیافته نمیکند — ویجت فرزند میتواند کوچکتر باشد و فضای باقیمانده خالی میماند. طبق مستندات رسمی Flutter (2026)، Flexible در سناریوهایی که نیاز به توزیع انعطافپذیر فضا بدون کشش اجباری است ضروری میباشد: دکمههایی با حداقل عرض، بلوکهای متنی با اندازه طبیعی و عناصر با intrinsic constraints.
نکات اصلی
Flexible — یک ویجت پوششی است که به عنصر فرزند فضای انعطافپذیر در کانتینر Flex ارائه میدهد. Flexible مانند Expanded در توزیع فضای آزاد شرکت میکند، اما با تفاوت کلیدی: فرزند Flexible میتواند فضای کمتری از آنچه به او اختصاص داده شده اشغال کند، اگر اندازه خودش از فضای موجود کوچکتر باشد.
Flexible از الگوریتم Flex فلاتر برای محاسبه فضای موجود استفاده میکند. ابتدا فریمورک همه فرزندان غیرانعطافپذیر (ویجتهای بدون Flexible/Expanded) را پرسوجو کرده و intrinsic size آنها را محاسبه میکند. فضای باقیمانده بین فرزندان انعطافپذیر به نسبت flex-factor آنها تقسیم میشود. پس از تخصیص فضا، Flexible fit را بررسی میکند — اگر loose باشد، محدودیت «بیشتر از مقدار اختصاصیافته نه» به عنصر فرزند اعمال میشود و به آن اجازه میدهد کوچک بماند.
ویژگی Flexible: اگر ویجت فرزند اندازههای حداقل خود را داشته باشد (مثلاً Text با رشته طولانی)، Flexible فضای درخواستی را اختصاص میدهد نه اینکه اجباری بکشد. این باعث میشود Flexible برای عناصری که اندازه آنها باید توسط محتوا تعیین شود نه کانتینر، غیرقابل جایگزین باشد.
نتیجه: وقتی نیاز به رزرو فضا برای یک عنصر دارید اما نمیخواهید آن را مجبور به کشیدن کنید از Flexible استفاده کنید. این کار اندازههای طبیعی محتوا را در توزیع انعطافپذیر layout حفظ میکند.
FlexFit — یک شمارش از دو مقدار: tight و loose. بستگی به انتخاب fit دارد که آیا ویجت فرزند به اندازه فضای اختصاصیافته اجباری کشیده میشود یا خیر.
FlexFit.tight: عنصر فرزند tight constraints دریافت میکند — اندازه حداقل و حداکثر برابر با فضای اختصاصیافته است. فرزند باید دقیقاً به اندازهای که الگوریتم Flex اختصاص داده فضا اشغال کند. اگر فرزند کوچکتر باشد — کشیده میشود. اگر بزرگتر باشد — فشرده میشود. رفتار مشابه Expanded.
FlexFit.loose: عنصر فرزند loose constraints دریافت میکند — حداقل اندازه ۰ است، حداکثر برابر با فضای اختصاصیافته است. فرزند میتواند هر اندازهای از ۰ تا maximum داشته باشد. اگر فرزند کوچک باشد (مثلاً Text با رشته کوتاه)، عرض طبیعی خود را میگیرد و بقیه فضا خالی میماند.
نتیجه: FlexFit.loose — انتخاب برای بلوکهای متنی و عناصر با اندازه طبیعی. FlexFit.tight — برای layoutهای ستونی سخت که همه عناصر باید عرض یا ارتفاع یکسان داشته باشند.
Flexible و Expanded شبیه به نظر میرسند اما وظایف متفاوتی را حل میکنند. Expanded همیشه فرزند را روی کل فضای موجود میکشد. Flexible میتواند فضای خالی اطراف فرزند باقی بگذارد اگر اندازه محتوا از سهم اختصاصیافته کوچکتر باشد.
سناریوی Flexible: داخل Row دو دکمه قرار دارد. اولی — «خرید» (متن کوتاه)، دومی — «افزودن به سبد خرید» (متن بلند). با Expanded هر دو دکمه به عرض مساوی کشیده میشوند و متن کوتاه حاشیههای بزرگی خواهد داشت. با Flexible هر دکمه عرض متن خود را میگیرد و فضای آزاد بین آنها یا در لبهها باقی میماند.
سناریوی Expanded: داخل Column سه کارت وجود دارد که باید بدون توجه به محتوا ارتفاع مساوی داشته باشند. Expanded ارتفاع موجود را به طور مساوی تقسیم میکند و هر کارت به اندازه یکسان کشیده میشود. Flexible با loose در اینجا مناسب نیست — کارت کوچک کوچک میماند و طراحی یکپارچه را نقض میکند.
نتیجه: وقتی محتوا اندازه عنصر را تعیین میکند و فضای خالی اطراف آن مجاز است Flexible را انتخاب کنید. وقتی همه عناصر بدون توجه به محتوا باید اندازه یکسان داشته باشند Expanded را انتخاب کنید.
مثال ۱ استفاده پایه از Flexible با FlexFit.loose در Row را نشان میدهد.
Row(
children: [
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.amber,
child: const Text('کوتاه'),
),
),
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.cyan,
child: const Text('متن طولانی برای نمایش'),
),
),
],
)
در مثال هر دو Flexible با loose fit. اولین کانتینر با متن کوتاه عرض طبیعی خود را میگیرد. دومی با متن بلند — عرض خود را. Row به هر کدام نیمی از عرض موجود را اختصاص میدهد، اما loose fit به کانتینرها اجازه میدهد کوچکتر باشند و فضای آزاد بین آنها خالی میماند.
مثال ۲ — مقایسه Flexible با Tight و Loose fit در Column.
Column(
children: [
Flexible(
fit: FlexFit.tight,
child: const Card(
child: ListTile(
title: Text('Tight — کشیده شده به ارتفاع کامل'),
),
),
),
const SizedBox(
height: 8,
),
Flexible(
fit: FlexFit.loose,
child: const Card(
child: ListTile(
title: Text('Loose — ارتفاع طبیعی'),
),
),
),
],
)
در Column اولین Flexible (tight) Card را روی نصف ارتفاع موجود میکشد. دومین Flexible (loose) — Card ارتفاع متناسب با محتوا را میگیرد و بقیه فضا خالی میماند. از نظر بصری مشخص است که tight ناحیه را اجباری پر میکند در حالی که loose اندازه فشرده را حفظ میکند.
نتیجه: در کد production از Flexible با loose برای فیلدهای فرم، دکمهها و بلوکهای متنی استفاده میشود. Flexible با tight — معادل Expanded و برای توزیع مساوی استفاده میشود.
خطای ۱: استفاده از Flexible خارج از کانتینر Flex. مانند Expanded، Flexible LayoutException را پرتاب میکند اگر داخل Row، Column یا Flex نباشد. راهحل: همیشه زنجیره والد ویجتها را بررسی کنید.
خطای ۲: اشتباه گرفتن Flexible و Expanded. توسعهدهندگان اغلب وقتی Flexible با loose fit نیاز است از Expanded استفاده میکنند و برعکس. نتیجه: Expanded عنصر را با متن کوتاه میکشد و فضاهای خالی بزرگ ایجاد میکند. راهحل: اگر اندازه عنصر میتواند از فضای اختصاصیافته کوچکتر باشد از Flexible(fit: FlexFit.loose) استفاده کنید.
خطای ۳: flex-factor صفر. Flexible با flex=0 مانند یک ویجت غیرانعطافپذیر رفتار میکند که ممکن است واضح نباشد. توسعهدهنده انتظار رفتار انعطافپذیر دارد اما عنصر حداقل اندازه را میگیرد. راهحل: برای توزیع فعال فضا flex باید ≥۱ باشد.
خطای ۴: Flexible داخل ScrollView بدون محدودیت اندازه. اگر Flexible در Column داخل SingleChildScrollView باشد، کانتینر scroll فضای بینهایت میدهد و توزیع flex کار نمیکند. راهحل: اندازه کانتینر scroll را از طریق SizedBox یا ConstrainedBox محدود کنید.
نتیجه: Flexible به همان اندازه Expanded به زمینه والد نیاز دارد. تفاوت فقط در fit است — آگاهانه بسته به وظیفه انتخاب کنید.
سوالات متداول
Expanded — Flexible با fit=tight ثابت است. تفاوت در این است که Expanded به پر کردن کل فضای موجود مقید است، در حالی که Flexible میتواند از loose fit برای حفظ اندازه طبیعی فرزند استفاده کند.
برای دکمههایی با طول متن متفاوت از Flexible(fit: FlexFit.loose) استفاده کنید. هر دکمه عرض متناسب با محتوای خود را میگیرد و بین آنها نابرابری ایجاد نمیشود. Expanded همه دکمهها را به عرض یکسان در میآورد.
fit: FlexFit.tight را تنظیم کنید — Flexible فرزند را مجبور به پر کردن کل فضای اختصاصیافته میکند. در این حالت Flexible از نظر رفتار کاملاً مشابه Expanded است.
بله، اگر فرزند از فضای اختصاصیافته بزرگتر باشد. Flexible constraints را با حداکثر اندازه برابر با سهم کانتینر Flex منتقل میکند. اگر فرزند از این اندازه تجاوز کند، در محدوده constraints فشرده میشود.
بله، Flexible با هر کانتینر Flex از جمله Row، Column و ویجت پایه Flex با direction دلخواه کار میکند. Flex امکان تنظیم جهتهای غیراستاندارد را از طریق mainAxisAlignment و crossAxisAlignment فراهم میکند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید