هيكل الشاشة في Flutter: Scaffold و AppBar بالتفصيل
استخدمت Scaffold في كل شاشة كتبتها حتى الآن، لكنك استعملت منه جزأين فقط: appBar و body. الحقيقة أن Scaffold فيه أماكن جاهزة لكل ما تراه في التطبيقات: شريط علوي بأزرار، وزر عائم، وشريط سفلي، وقائمة جانبية. في هذا الدرس ستتعرف على هذه الأماكن واحداً واحداً.
خريطة Scaffold
Section titled “خريطة Scaffold”تخيّل Scaffold مثل مخطط شقة جاهز: الغرف محددة سلفاً، وأنت فقط تضع الأثاث في كل غرفة.
┌──────────────────────────┐│ appBar │ ← الشريط العلوي├──────────────────────────┤│ ││ body │ ← المحتوى الرئيسي│ ││ ( + ) │ ← floatingActionButton├──────────────────────────┤│ bottomNavigationBar │ ← الشريط السفلي└──────────────────────────┘| الخاصية | مكانها |
|---|---|
appBar |
الشريط العلوي |
body |
المساحة الرئيسية |
floatingActionButton |
زر عائم فوق المحتوى |
bottomNavigationBar |
شريط التنقل السفلي |
drawer |
قائمة جانبية تنسحب من الحافة |
backgroundColor |
لون خلفية الشاشة |
لا يشترط أن تملأ كل الأماكن. استخدم ما تحتاجه فقط، وكلها اختيارية.
AppBar: أكثر من عنوان
Section titled “AppBar: أكثر من عنوان”AppBar( title: const Text('الرسائل'), centerTitle: true, backgroundColor: Colors.indigo, foregroundColor: Colors.white, leading: IconButton( icon: const Icon(Icons.menu), onPressed: () {}, ), actions: [ IconButton( icon: const Icon(Icons.search), tooltip: 'بحث', onPressed: () {}, ), IconButton( icon: const Icon(Icons.notifications_none), tooltip: 'الإشعارات', onPressed: () {}, ), ],)title: العنوان، وغالباً يكونText، لكنه يقبل أي Widget، حتى حقل بحث.centerTitle: هل يتوسط العنوان الشريط؟backgroundColor: لون الشريط، وforegroundColor: لون العنوان والأيقونات معاً.leading: Widget في بداية الشريط (اليمين في التطبيق العربي). إذا تركته فارغاً يضع Flutter سهم الرجوع تلقائياً في الشاشات الفرعية.actions: قائمة أزرار في نهاية الشريط.tooltip: نص يظهر عند الضغط المطول على الزر، ويقرؤه قارئ الشاشة للمكفوفين. اكتبه دائماً لأزرار الأيقونات.
القائمة المنسدلة: PopupMenuButton
Section titled “القائمة المنسدلة: PopupMenuButton”زر الثلاث نقاط الذي يفتح قائمة صغيرة:
PopupMenuButton<String>( onSelected: (value) { debugPrint('اختار المستخدم: $value'); }, itemBuilder: (context) => const [ PopupMenuItem(value: 'settings', child: Text('الإعدادات')), PopupMenuItem(value: 'help', child: Text('المساعدة')), PopupMenuItem(value: 'logout', child: Text('تسجيل الخروج')), ],)<String>: نوع القيمة التي يحملها كل عنصر.itemBuilder: دالة تُرجع عناصر القائمة، ولكل عنصرvalueتميّزه وchildيظهر للمستخدم.onSelected: تُستدعى عند اختيار عنصر، وتستقبل قيمته.
ضع هذا الزر كآخر عنصر في actions.
الزر العائم: FloatingActionButton
Section titled “الزر العائم: FloatingActionButton”الزر العائم يمثل الإجراء الأهم في الشاشة: «رسالة جديدة» في تطبيق المحادثات، أو «إضافة مهمة» في تطبيق المهام.
FloatingActionButton.extended( onPressed: () {}, icon: const Icon(Icons.edit), label: const Text('رسالة جديدة'),)FloatingActionButton: دائري بأيقونة فقط.FloatingActionButton.extended: ممتد بأيقونة ونص.FloatingActionButton.small: نسخة أصغر.
ومكانه يتحدد من Scaffold بالخاصية floatingActionButtonLocation:
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,القيمة الافتراضية endFloat تضعه في نهاية الشاشة من الأسفل، و centerFloat في المنتصف.
SafeArea: احمِ محتواك من الحواف
Section titled “SafeArea: احمِ محتواك من الحواف”الهواتف الحديثة فيها نتوء للكاميرا، وزوايا دائرية، وشريط للحالة فيه الساعة والبطارية. إذا لم تستخدم AppBar، فقد يختفي جزء من محتواك تحت هذه الأشياء. الحل SafeArea:
const Scaffold( body: SafeArea( child: Text('هذا النص لن يختفي تحت شريط الحالة'), ),)SafeArea تضيف مسافات حول ابنها بمقدار المناطق غير الآمنة في الجهاز الحالي. و AppBar يتعامل مع هذا تلقائياً، لذلك تحتاج SafeArea أساساً في الشاشات التي بلا شريط علوي، مثل شاشة الترحيب أو تسجيل الدخول.
الشريط السفلي والقائمة الجانبية
Section titled “الشريط السفلي والقائمة الجانبية”bottomNavigationBar و drawer يستحقان درساً كاملاً، وستتعلمهما بالتفصيل في درس التنقل السفلي والتبويبات. لكن لتعرف شكلهما:
Scaffold( appBar: AppBar(title: const Text('الرئيسية')), drawer: const Drawer( child: Center(child: Text('القائمة الجانبية')), ), body: const Center(child: Text('المحتوى')),)بمجرد أن تضيف drawer، يضع Flutter زر القائمة (ثلاث شرطات) في AppBar تلقائياً، ويفتح القائمة عند الضغط عليه أو عند السحب من حافة الشاشة.
المشروع: شاشة صندوق الوارد
Section titled “المشروع: شاشة صندوق الوارد”class InboxScreen extends StatefulWidget { const InboxScreen({super.key});
@override State<InboxScreen> createState() => _InboxScreenState();}
class _InboxScreenState extends State<InboxScreen> { String _status = 'لا توجد رسائل جديدة';
void _show(String text) { setState(() { _status = text; }); }
@override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey.shade100, appBar: AppBar( title: const Text('صندوق الوارد'), centerTitle: true, actions: [ IconButton( icon: const Icon(Icons.search), tooltip: 'بحث', onPressed: () => _show('ضغطت على البحث'), ), PopupMenuButton<String>( onSelected: (value) => _show('اخترت: $value'), itemBuilder: (context) => const [ PopupMenuItem(value: 'الإعدادات', child: Text('الإعدادات')), PopupMenuItem(value: 'المساعدة', child: Text('المساعدة')), ], ), ], ), drawer: const Drawer( child: SafeArea( child: Padding( padding: EdgeInsets.all(16), child: Text('مجلدات البريد'), ), ), ), body: Center( child: Text(_status, style: const TextStyle(fontSize: 18)), ), floatingActionButton: FloatingActionButton.extended( onPressed: () => _show('رسالة جديدة فارغة'), icon: const Icon(Icons.edit), label: const Text('رسالة جديدة'), ), ); }}كيف تعمل الشاشة:
- في المنتصف نص يعرض آخر شيء فعله المستخدم.
- أيقونة البحث تغيّر النص إلى «ضغطت على البحث».
- زر الثلاث نقاط يفتح قائمة، واختيار «الإعدادات» يغيّر النص إلى «اخترت: الإعدادات».
- زر القائمة في بداية الشريط ظهر تلقائياً لأننا أضفنا
drawer. - الزر العائم يكتب «رسالة جديدة فارغة».
جرّب بنفسك
Section titled “جرّب بنفسك”- شغّل شاشة صندوق الوارد وجرّب كل زر فيها.
- غيّر لون الشريط العلوي بـ
backgroundColorوforegroundColor. - انقل الزر العائم إلى منتصف الشاشة من الأسفل.
- تحدٍّ: أضف عنصراً ثالثاً للقائمة المنسدلة اسمه «تصفير»، يعيد النص إلى «لا توجد رسائل جديدة».
أخطاء شائعة
Section titled “أخطاء شائعة”- وضع Scaffold داخل Scaffold: كل شاشة لها
Scaffoldواحد. التكرار يسبب شريطين علويين ومسافات غريبة. - نسيان tooltip لأزرار الأيقونات: المستخدم الذي يعتمد على قارئ الشاشة لن يعرف وظيفة الزر.
- محتوى يختفي تحت نتوء الكاميرا: في الشاشات التي بلا
AppBar، لف المحتوى بـSafeArea.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
أين تضع أزرار البحث والإشعارات في الشريط العلوي؟
actions قائمة من الـ Widgets تظهر في نهاية AppBar، وهي المكان المعتاد لأزرار الإجراءات.
سؤال
ما وظيفة SafeArea؟
SafeArea تضيف مسافات بمقدار المناطق التي قد تغطيها أجزاء الجهاز، فيبقى المحتوى ظاهراً كله.
الخلاصة
Section titled “الخلاصة”Scaffoldمخطط جاهز للشاشة:appBarوbodyوfloatingActionButtonوbottomNavigationBarوdrawer.AppBarيقبلleadingفي البداية وactionsفي النهاية، معcenterTitleوالألوان.PopupMenuButtonيجمع الإجراءات الثانوية في قائمة بثلاث نقاط.- زر عائم واحد للإجراء الأهم، ويتحدد مكانه بـ
floatingActionButtonLocation. SafeAreaتحمي المحتوى في الشاشات التي بلا شريط علوي.