AppBar

ما هي AppBar؟

شريط علوي مادي (Material) يُعرض عادةً داخل:

Scaffold(appBar: AppBar(...))
Dart

يوفّر عنوان الصفحة، أزرار رجوع/قائمة، إجراءات (actions)، تبويبات… إلخ.

أهم الخصائص (مع الشرح السريع)
بنية المحتوى
  • leading: Widget?
    العنصر في أقصى اليسار (Android) / أقصى اليمين (RTL). افتراضيًا:
    • زر رجوع إن وُجد مسار سابق في Navigator.
    • زر قائمة (hamburger) إن كان هناك Scaffold.drawer ولا يوجد مسار سابق.
    • عيّنه يدويًا لتخصيصه (مثل شعار أو زر مخصص).
  • automaticallyImplyLeading: bool (افتراضي true)
    هل يُولِّد زر الرجوع/القائمة تلقائيًا؟ اجعله false لإخفائه إن وضعت leading مخصّصًا.
  • title: Widget?
    عادة Text('العنوان'). يمكنك وضع أي ويدجت (حتى حقل بحث).
  • actions: List<Widget>?
    Widgets في الطرف المقابل لـ leading (مثل أزرار البحث، الإشعارات، قائمة منسدلة).
  • flexibleSpace: Widget?
    طبقة خلف الـ AppBar (تحت العنوان والأزرار). ممتازة للخلفيات المتدرجة/الصور/الـ blur.
  • bottom: PreferredSizeWidget?
    شريط سفلي أسفل الـ AppBar (مثل TabBar أو أي ويدجت داخل PreferredSize).
الألوان والارتفاع والظل
  • backgroundColor: Color?
    لون الخلفية.
  • foregroundColor: Color?
    يؤثر على لون النصوص/الأيقونات داخل الـ AppBar.
  • elevation: double?
    ظلّ الشريط (0 لإلغاء الظل).
  • shadowColor: Color?
    لون الظل.
  • surfaceTintColor: Color? (Material 3)
    صبغة على السطح؛ ألغِ تأثيراتها بـ forceMaterialTransparency: true.
  • scrolledUnderElevation: double? (Material 3)
    ظل إضافي عندما يمرّ المحتوى أسفل الـ AppBar أثناء التمرير.
التخطيط والمحاذاة
  • centerTitle: bool?
    محاذاة العنوان للوسط. (بعض المنصات تُوسّطه افتراضيًا؛ استخدمه للتثبيت).
  • titleSpacing: double?
    المسافة الأفقية حول العنوان. القيمة الافتراضية مناسبة غالبًا.
  • toolbarHeight: double?
    ارتفاع شريط الأدوات (الافتراضي kToolbarHeight = 56).
  • leadingWidth: double?
    عرض مساحة leading (مفيد لوضع شعار عريض).
  • primary: bool (افتراضي true)
    إن كان true يحترم مساحة شريط الحالة (status bar). اجعله false إذا استخدمته بعيدًا عن أعلى الشاشة.
النصوص والأنماط
  • titleTextStyle, toolbarTextStyle
    تخصيص نمط النصوص (يمكن أيضًا عبر AppBarTheme).
  • iconTheme, actionsIconTheme
    تخصيص نمط الأيقونات في الجهتين.
الشكل والقصّ والتراكب على النظام
  • shape: ShapeBorder?
    حواف سفلية منحنية مثل: shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(bottom: Radius.circular(24)), )
  • clipBehavior: Clip
    لقصّ المحتوى تبعًا للشكل.
  • systemOverlayStyle: SystemUiOverlayStyle?
    لتحديد لون/سطوع شريط الحالة (أيقونات بيضاء أو داكنة). مثال: systemOverlayStyle: SystemUiOverlayStyle.light
  • excludeHeaderSemantics: bool
    لحالات إمكانية الوصول (نادراً ما تغيّره).
  • forceMaterialTransparency: bool (M3)
    يجعل الخلفية شفافة ويعطّل طبقات الصبغة الافتراضية.
أمثلة عملية
1) أبسط AppBar
Scaffold(
  appBar: AppBar(
    title: Text('الرئيسية'),
  ),
)
Dart
2) AppBar مع actions وleading مخصص
AppBar(
  leading: IconButton(
    icon: Icon(Icons.arrow_back),
    onPressed: () => Navigator.pop(context),
  ),
  title: Text('الصفحة'),
  actions: [
    IconButton(icon: Icon(Icons.search), onPressed: () {}),
    PopupMenuButton<String>(
      onSelected: (v) {},
      itemBuilder: (_) => [
        PopupMenuItem(value: 's1', child: Text('إعدادات')),
        PopupMenuItem(value: 's2', child: Text('حول')),
      ],
    ),
  ],
)
Dart
3) AppBar مع تبويبات (TabBar)

تحتاج DefaultTabController.

DefaultTabController(
  length: 3,
  child: Scaffold(
    appBar: AppBar(
      title: Text('أقسام'),
      bottom: TabBar(
        tabs: [
          Tab(text: 'الكل'),
          Tab(text: 'المفضلة'),
          Tab(text: 'حديث'),
        ],
      ),
    ),
    body: TabBarView(
      children: [/* Widgets */ Container(), Container(), Container()],
    ),
  ),
);
Dart
4) تدرّج لوني عبر flexibleSpace
AppBar(
  title: Text('متدرّج'),
  elevation: 0,
  flexibleSpace: Container(
    decoration: BoxDecoration(
      gradient: LinearGradient(
        begin: Alignment.topRight,
        end: Alignment.bottomLeft,
        colors: [Colors.teal, Colors.blue],
      ),
    ),
  ),
)
Dart
5) AppBar شفاف فوق صورة (Hero header)

مهم: extendBodyBehindAppBar: true وتهيئة التراكب.

Scaffold(
  extendBodyBehindAppBar: true,
  appBar: AppBar(
    backgroundColor: Colors.transparent,
    elevation: 0,
    systemOverlayStyle: SystemUiOverlayStyle.light, // أيقونات بيضاء
  ),
  body: Stack(
    fit: StackFit.expand,
    children: [
      Image.network('https://picsum.photos/1200/800', fit: BoxFit.cover),
      // محتوى…
    ],
  ),
);
Dart
6) AppBar مع Drawer تلقائي
Scaffold(
  appBar: AppBar(title: Text('قائمة')),
  drawer: Drawer(child: ListView(children: [ListTile(title: Text('عنصر'))])),
  body: Container(),
);
Dart

عند إضافة drawer، سيظهر زر القائمة تلقائيًا في leading (ما لم تعيّنه يدويًا).

7) bottom مخصص بارتفاع معين
AppBar(
  title: Text('ترويسة'),
  bottom: PreferredSize(
    preferredSize: Size.fromHeight(48),
    child: Container(
      height: 48,
      alignment: Alignment.center,
      child: Text('شريط سفلي مخصص'),
    ),
  ),
)
Dart
تخصيص شامل عبر Theme

بدل تكرار الأنماط في كل صفحة، استخدم AppBarTheme:

MaterialApp(
  theme: ThemeData(
    useMaterial3: true, // اختياري
    appBarTheme: AppBarTheme(
      backgroundColor: Colors.white,
      foregroundColor: Colors.black87,
      elevation: 0,
      centerTitle: true,
      systemOverlayStyle: SystemUiOverlayStyle.dark,
      titleTextStyle: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
      iconTheme: IconThemeData(size: 22),
    ),
  ),
  home: Scaffold(appBar: AppBar(title: Text('مثال'))),
);
Dart
نصائح ذهبية ومحاذير
  • Drawer: إذا لديك Scaffold.drawer ولم تضع leading، سيظهر زر الـ menu تلقائيًا. لـ endDrawer لا يوجد زر تلقائي—أضِفه في actions أو leading: IconButton( icon: Icon(Icons.menu_open), onPressed: () => Scaffold.of(context).openEndDrawer(), ) استخدم Builder للحصول على context الصحيح داخل AppBar.
  • عنوان طويل: استخدم title: Text('عنوان طويل جدًا', overflow: TextOverflow.ellipsis) أو اجعل العنوان ويدجت مرنة.
  • شفافية تامة: اجمع بين
    backgroundColor: Colors.transparent, elevation: 0, وقد تحتاج scrolledUnderElevation: 0 مع M3.
  • التباين مع شريط الحالة: غيّر systemOverlayStyle ليتناسب لون أيقونات شريط الحالة مع الخلفية (فاتحة/داكنة).
  • primary: false
    استخدمه عندما تضع AppBar داخل منطقة ليست أعلى الشاشة (داخل NestedScrollView أو قسم داخلي).
  • TabBar: تأكد من وجود DefaultTabController ومواءمة length مع عدد التبويبات.
  • ⚠️ لا تخلط خصائص SliverAppBar هنا
    خصائص مثل pinned/floating/snap تخص SliverAppBar ضمن CustomScrollView/NestedScrollView.
    إن احتجت سلوكًا مرنًا مع التمرير—فكّر باستخدام SliverAppBar.
  • ⚠️ M2 vs M3
    عند useMaterial3: true قد تتغيّر بعض السلوكيات الافتراضية (ظلال، صبغات). استخدم forceMaterialTransparency أو عدّل AppBarTheme لضبط المظهر.
أسئلة شائعة سريعة
  • كيف أزيل خط الظل؟
    elevation: 0 (+ scrolledUnderElevation: 0 في M3).
  • كيف أوسّط العنوان دائمًا؟
    centerTitle: true.
  • كيف أضع حقل بحث داخل AppBar؟
    إمّا في title: title: TextField( decoration: InputDecoration(hintText: 'ابحث...', border: InputBorder.none), ) أو ضع شريط البحث في bottom.
  • كيف أضع صورة/تدرّج؟
    استخدم flexibleSpace مع Container + decoration.