Expanded: ما هو وكيف يعمل في Flutter

المؤلف: IT Sectr نُشر: 2026-07-03 وقت القراءة: 6 دق

Expanded هو عنصر واجهة (widget) في Flutter يُجبر العنصر الفرعي على ملء كل المساحة المتاحة في حاوية Flex. عندما يقوم Row أو Column بتوزيع المساحة بين العناصر الفرعية، يأخذ Expanded المساحة الحرة بعد حساب العناصر غير المرنة. وفقًا للتوثيق الرسمي لـ Flutter (2026)، يُعد Expanded أحد أكثر عناصر التخطيط استخدامًا: فهو يُطبق في الواجهات النسبية المئوية، بناء البطاقات، القوائم واللوحات. ميزته الرئيسية هي الحساب التلقائي للعرض أو الارتفاع بناءً على معامل flex دون تحديد الأبعاد بشكل صريح.

النقاط الرئيسية

  • Expanded هو عنصر تخطيط يمد العنصر الفرعي لملء كل المساحة المتاحة في Row أو Column أو Flex
  • معامل Flex يحدد حصة المساحة الحرة التي سيحصل عليها كل Expanded
  • Expanded يختلف عن Flexible بأنه يملأ كل المساحة المتاحة بشكل إجباري
  • Stack لا يدعم Expanded، فقط Row و Column و Flex
  • خطأ استخدام Expanded خارج حاوية Flex يسبب LayoutException

ما هو Expanded

Expanded هو عنصر غلاف (wrapper widget) يأخذ عنصرًا فرعيًا ويجبره على التمدد لملء المساحة المتاحة في حاوية Flex (Row, Column, Flex). لا يمتلك Expanded تمثيلًا بصريًا خاصًا به — فهو يدير فقط القيود (constraints) المنقولة إلى العنصر الفرعي.

في جوهر Expanded تكمن آلية Flex التي يوفرها إطار Flutter. عندما يحسب Row أو Column أحجام أبنائهما، يخصصان أولاً مساحة للعناصر غير المرنة (العناصر العادية ذات الأحجام الثابتة)، ثم يوزعان المساحة المتبقية بين أبناء Expanded و Flexible بشكل متناسب مع معاملات flex الخاصة بهم.

يستخدم Expanded Flexible.fit = FlexFit.tight. هذا يعني أن ابن Expanded يجب أن يشغل كل المساحة المخصصة، حتى لو كان حجمه أصغر. على عكس Flexible مع Fit.loose، حيث يمكن أن يكون الابن أصغر من المساحة المخصصة، يقوم Expanded بتمديد المحتوى بشكل إجباري.

الخلاصة: Expanded هو الأداة الرئيسية لإنشاء تخطيطات متناسبة في Flutter. استخدمه عندما تحتاج إلى أن يملأ عنصر كل العرض أو الارتفاع المتاح بشكل مضمون.

Expanded ضد Flexible: الفروقات الرئيسية

Expanded و Flexible كلاهما يوزع المساحة في حاويات Flex، لكنهما يتصرفان بشكل مختلف جوهريًا. يكمن الاختلاف في خاصية fit، التي تحدد ما إذا كان الابن يمكن أن يكون أصغر من المساحة المتاحة.

لدى Expanded نموذج سلوك صارم: fit الخاص به يساوي FlexFit.tight. هذا يعني أن العنصر الفرعي يتلقى قيودًا مساوية للمساحة المتاحة — لا أكثر ولا أقل. إذا كان الابن أصغر، فإنه يتمدد. إذا كان أكبر، فإنه ينكمش. يستخدم Flexible FlexFit.loose، مما يسمح للعنصر الفرعي أن يكون بأي حجم ضمن المساحة المخصصة.

عمليًا: إذا كانت Row تحتوي على Expanded مع flex=1، فسيشغل كل منهما نصف العرض بالضبط. إذا استبدلتهما بـ Flexible مع fit.loose، فقد يكون كل ابن أصغر من النصف إذا كان حجمه أصغر — ستبقى المساحة المتبقية فارغة.

الخلاصة: استخدم Expanded للتخطيطات المتناسبة الصارمة، و Flexible عندما يمكن أن يكون الابن أصغر من المساحة المتاحة. إذا لم تكن متأكدًا — ابدأ بـ Expanded، فهو يعطي سلوكًا أكثر قابلية للتنبؤ.

معامل Flex: كيف يتم توزيع المساحة

معامل Flex (parameter flex) هو قيمة رقمية تحدد حصة المساحة المتاحة التي سيحصل عليها Expanded. افتراضيًا flex=1، مما يعني توزيعًا متساويًا بين جميع أبناء Expanded.

تعمل خوارزمية التوزيع على ثلاث خطوات. أولاً: يحسب Flutter الحجم الجوهري لجميع الأبناء غير المرنين. ثانيًا: تقسيم المساحة المتبقية على مجموع جميع معاملات flex. ثالثًا: يحصل كل Expanded على حصة تساوي معامل flex الخاص به مضروبًا في حجم وحدة flex واحدة.

على سبيل المثال، Row بعرض 300px تحتوي على Expanded: الأول بـ flex=2، والثاني بـ flex=1. المساحة الحرة (300px ناقص الأبناء غير المرنين) تُقسم إلى 3 أجزاء. الأول يحصل على 2/3، والثاني على 1/3. إذا لم يكن هناك أبناء غير مرنين، الأول يحصل على 200px، والثاني على 100px.

يمكن أن يكون معامل flex أي عدد صحيح موجب. القيمة 0 هي حالة خاصة: Expanded مع flex=0 يتصرف كعنصر غير مرن عادي، مشغلاً الحد الأدنى من المساحة حسب حجم الابن. هذا السلوك مكافئ لعدم وجود Expanded.

الخلاصة: معامل flex هو المفتاح لبناء تخطيطات مرنة. استخدم النسب 1:1 للأعمدة المتساوية، 2:1 للوحات مع منطقة رئيسية وجانبية، 3:1 للواجهات ذات التنقل الضيق.

أمثلة كود مع Expanded

مثال 1 يوضح الاستخدام الأساسي لـ Expanded في Row لإنشاء ثلاثة أعمدة متساوية.

dart
Row(
  children: [
    Expanded(
      child: Container(
        color: Colors.red,
      ),
    ),
    Expanded(
      child: Container(
        color: Colors.green,
      ),
    ),
    Expanded(
      child: Container(
        color: Colors.blue,
      ),
    ),
  ],
)

في هذا المثال، ثلاث Expanded مع flex=1 (افتراضيًا) تقسم عرض Row بالتساوي. تمتد الحاويات إلى الارتفاع الكامل المحدد بواسطة Row وتشغل حصصًا متساوية. هذا النهج مناسب لإنشاء تخطيطات قائمة على الأعمدة بتوزيع نسبي.

مثال 2 يوضح استخدام معاملات flex مختلفة لإنشاء تخطيط مع شريط جانبي ومحتوى رئيسي.

dart
Row(
  children: [
    Expanded(
      flex: 1,
      child: Container(
        color: Colors.grey.200,
        child: const Center(
          child: Text('الشريط الجانبي'),
        ),
      ),
    ),
    Expanded(
      flex: 3,
      child: Container(
        color: Colors.white,
        child: const Center(
          child: Text('منطقة المحتوى'),
        ),
      ),
    ),
  ],
)

المثال الثاني ينشئ تخطيطًا نموذجيًا مع شريط جانبي (25%) ومنطقة محتوى رئيسي (75%). flex=1 و flex=3 يعطيان نسبة 1:3. عندما يتغير عرض الشاشة، تُحفظ النسب تلقائيًا — هذا هو أساس الواجهات المتجاوبة.

الخلاصة: Expanded مع معاملات flex مختلفة هو أداة قياسية لبناء تخطيطات متجاوبة. الجمع بين Expanded في Column يسمح بإنشاء ترتيبات نسبية أفقية وعمودية.

الأخطاء الشائعة عند استخدام Expanded

خطأ 1: استخدام Expanded خارج Row أو Column أو Flex. إذا وضعت Expanded مباشرة في Stack أو ListView أو أي حاوية أخرى غير Flex، يطلق Flutter LayoutException مع الرسالة "Expanded widgets must be placed inside Flex widgets". الحل: تحقق من العنصر الأب — فقط Row أو Column أو Flex.

خطأ 2: وضع Expanded داخل ListView دون تحديد shrinkWrap. ListView افتراضيًا له ارتفاع لا نهائي في اتجاه التمرير، ولا يستطيع Expanded حساب حصته. الحل: استخدم shrinkWrap: true أو لف ListView في SizedBox بارتفاع ثابت.

خطأ 3: Expanded متعددة مع flex إجمالي يتجاوز المساحة المتاحة. إذا كانت Row ذات عرض محدود تحتوي على Expanded بالإضافة إلى عناصر ذات حجم جوهري كبير، قد يحدث تجاوز (overflow). الحل: تحقق من الأحجام الدنيا للأبناء غير المرنين واستخدم FittedBox أو Flex fit إذا لزم الأمر.

خطأ 4: Expanded متداخلة في Column داخل Row. إذا كان Expanded داخل Column يحتوي على Expanded آخر داخل Row، قد ينشأ تضارب في القيود. الحل: حدد عمق التداخل أو استخدم ConstrainedBox لتحديد الأبعاد بشكل صريح في المستويات المتوسطة.

الخلاصة: Expanded يتطلب سياقًا أبويًا صحيحًا. تحقق دائمًا من أن Expanded موضوع مباشرة في Row أو Column أو Flex، وتجنب التداخل دون أبعاد صريحة.

الأسئلة الشائعة

ما الفرق بين Expanded و SizedBox.expand؟

SizedBox.expand يمد العنصر الفرعي قسرًا إلى الأبعاد المحددة بواسطة القيود الخارجية، لكنه لا يشارك في توزيع flex. يعمل Expanded فقط داخل حاويات Flex ويأخذ معامل flex في الاعتبار عند توزيع المساحة الحرة بين الأبناء.

هل يمكن استخدام Expanded داخل Stack؟

لا. Stack ليس حاوية Flex، واستخدام Expanded داخله سيسبب LayoutException. لتمديد الأبناء في Stack، استخدم Positioned.fill أو BoxConstraints.expand.

ماذا يحدث إذا لم أحدد معامل flex؟

افتراضيًا flex=1. جميع Expanded بدون flex صريح يحصلون على حصص متساوية من المساحة الحرة. إذا كانت Row تحتوي على ثلاث Expanded بدون flex، فسيشغل كل منها ثلث المساحة المتاحة بالضبط.

كيف أجعل Expanded فقط بالعرض وليس بالارتفاع؟

ضع Expanded في Row للتمديد الأفقي. للتمديد العمودي استخدم Expanded داخل Column. إذا كنت بحاجة إلى تحديد الأبعاد، لف Expanded أو ابنه في SizedBox.

هل يعمل Expanded مع Wrap أو عناصر Flex؟

Expanded يعمل مع Flex، بما في ذلك Row و Column كفئات فرعية. Wrap ليس حاوية Flex ولا يدعم Expanded. لتوزيع المساحة في Wrap استخدم طرقًا أخرى، مثل RunAlignment.

الخلاصة

  • Expanded هو عنصر للتمديد الإجباري للابن لملء كل المساحة المتاحة في حاوية Flex
  • معامل Flex يحدد نسبة توزيع المساحة الحرة بين عدة Expanded
  • الفرق عن Flexible: Expanded يستخدم tight fit (ملء إجباري)، Flexible يستخدم loose fit (اختياري)
  • خطأ وضع Expanded خارج Row أو Column أو Flex يسبب LayoutException
  • التجاوب: يتم الحفاظ على نسب التخطيط تلقائيًا عند تغيير حجم الشاشة
  • توصية: استخدم Expanded كأداة رئيسية لتخطيطات الأعمدة واللوحات في Flutter

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا