Card

ما هي Card؟

Card عنصر Material بزاويا مستديرة وظل (elevation) لعرض محتوى مترابط داخل بطاقة جميلة: عنوان، وصف، صورة، أزرار… إلخ.

تُستخدم بكثرة في صفحات التفاصيل، القوائم، الشبكات (Grid)، واللوحات المعلوماتية.

أهم الاستخدامات
  • بطاقات معلومات مختصرة (Profile/Contact).
  • بطاقات منتجات مع صورة وسعر وزر شراء.
  • عناصر قائمة أنيقة داخل ListView أو GridView.
  • بطاقات إعدادات مع أيقونة وعنوان ونص وصفي.
البنية الأساسية
Card(
  child: Padding(
    padding: const EdgeInsets.all(12),
    child: Text('محتوى البطاقة'),
  ),
)
Dart
مثال شائع باستخدام ListTile + أزرار
Card(
  child: Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      const ListTile(
        leading: Icon(Icons.album),
        title: Text('عنوان البطاقة'),
        subtitle: Text('نص وصفي مختصر عن المحتوى'),
      ),
      Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          TextButton(onPressed: () {}, child: const Text('تفاصيل')),
          const SizedBox(width: 8),
          TextButton(onPressed: () {}, child: const Text('مشاركة')),
          const SizedBox(width: 8),
        ],
      ),
    ],
  ),
)
Dart
الخصائص المهمة (مع الشرح المختصر)
  • child
    محتوى البطاقة (غالباً Column/ListTile/صور…).
  • color
    لون خلفية البطاقة. في Material 3 غالباً أفضل تركه للثيم، أو استخدمه عند الحاجة لتباين معيّن.
  • surfaceTintColor (مهم في Material 3)
    لون التوهّج/التظليل فوق السطح حسب الارتفاع (لإحساس العمق). يمكنك تعطيله بوضعه Colors.transparent إذا لا تريد تأثير التينت.
  • shadowColor
    لون الظل عند وجود elevation.
  • elevation
    ارتفاع البطاقة (قيمة أكبر = ظل أقوى). القيَم المعتدلة (1–4) تكفي غالباً.
  • margin
    مسافة خارجية حول البطاقة. إذا لا تريد مسافة افتراضية ضع EdgeInsets.zero.
  • shape
    شكل وحدود البطاقة: زوايا دائرية، حدود…
    مثال: dartCopyEditshape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: const BorderSide(color: Colors.grey), )
  • clipBehavior
    كيف يتم قصّ المحتوى (مهم لقص الصور حسب الزوايا الدائرية).
    مثال: clipBehavior: Clip.antiAlias
  • semanticContainer
    يتحكم بطريقة دمج معنويات الأطفال لقرّاء الشاشة (اتركه كما هو غالباً).

ملاحظة: Card لا تملك onTap—لو تريدها قابلة للنقر، لفّ المحتوى بـ InkWell أو InkResponse داخل البطاقة، مع التأكد من تطابق نصف القطر (radius) للحصول على تأثير تموّج جميل.

أمثلة عملية متنوعة
1) بطاقة قابلة للنقر (InkWell) مع تموّج متوافق مع الشكل
Card(
  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
  clipBehavior: Clip.antiAlias, // حتى يتم قص الرِبل داخل الحدود
  child: InkWell(
    onTap: () { print('تم النقر على البطاقة'); },
    child: Padding(
      padding: const EdgeInsets.all(16),
      child: Row(
        children: const [
          Icon(Icons.description),
          SizedBox(width: 12),
          Expanded(child: Text('انقر لفتح التفاصيل')),
        ],
      ),
    ),
  ),
)
Dart
2) بطاقة منتج بصورة علوية ونص وأزرار
Card(
  clipBehavior: Clip.antiAlias,
  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
  elevation: 2,
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      // قصّ الصورة حسب زوايا البطاقة تلقائياً بفضل clipBehavior
      Image.network(
        'https://picsum.photos/800/400',
        height: 160,
        width: double.infinity,
        fit: BoxFit.cover,
      ),
      Padding(
        padding: const EdgeInsets.all(12),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text('اسم المنتج', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
            const SizedBox(height: 6),
            const Text('وصف قصير للمنتج يوضح أهم الميزات.'),
            const SizedBox(height: 8),
            Row(
              children: [
                const Text('\$19.99', style: TextStyle(fontWeight: FontWeight.bold)),
                const Spacer(),
                ElevatedButton.icon(
                  onPressed: () {},
                  icon: const Icon(Icons.shopping_cart),
                  label: const Text('إضافة'),
                ),
              ],
            ),
          ],
        ),
      ),
    ],
  ),
)
Dart
3) بطاقة داخل شبكة GridView
GridView.builder(
  padding: const EdgeInsets.all(12),
  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 2,
    mainAxisSpacing: 12,
    crossAxisSpacing: 12,
    childAspectRatio: 3/4,
  ),
  itemCount: 8,
  itemBuilder: (context, index) {
    return Card(
      elevation: 1,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
      child: Center(child: Text('عنصر ${index + 1}')),
    );
  },
)
Dart
4) بطاقة بخلفية مخصّصة وحدود
Card(
  color: Colors.blueGrey.shade50,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(20),
    side: const BorderSide(color: Colors.blueGrey),
  ),
  child: const Padding(
    padding: EdgeInsets.all(16),
    child: Text('بطاقة بحدود وزوايا كبيرة'),
  ),
)
Dart
5) بطاقة إعدادات صغيرة داخل ListView
ListView(
  padding: const EdgeInsets.all(12),
  children: [
    Card(
      child: SwitchListTile(
        title: const Text('الإشعارات'),
        subtitle: const Text('تفعيل/تعطيل'),
        value: true,
        onChanged: (v) {},
        secondary: const Icon(Icons.notifications),
      ),
    ),
    Card(
      child: ListTile(
        leading: const Icon(Icons.lock),
        title: const Text('الخصوصية'),
        subtitle: const Text('إدارة الأذونات'),
        trailing: const Icon(Icons.chevron_right),
        onTap: () {},
      ),
    ),
  ],
)
Dart
نصائح احترافية
  • التفاعل (Ripple):
    ضع InkWell داخل البطاقة واجعل Card.clipBehavior وCard.shape متوافقين مع InkWell لضمان تموّج نظيف داخل الحدود.
  • الأداء:
    • لا ترفع elevation كثيراً بدون داعي (الظل مكلف في الرسم).
    • في الشبكات/القوائم الكبيرة، اجعل محتوى البطاقة بسيطاً واستخدم صوراً مُخفّضة/مخبأة (مثل cached_network_image).
    • استخدم const حيثما أمكن لتخفيف إعادة البناء.
  • التصميم (Material 3):
    جرّب ترك color الافتراضي لتستفيد من Surface/SurfaceVariant وsurfaceTintColor. إن لم تُعجبك طبقة التينت، اضبط surfaceTintColor: Colors.transparent.
  • الهوامش والمساحات:
    • Card لديها هامش خارجي افتراضي صغير؛ غيّره حسب الحاجة بـ margin.
    • داخل البطاقة، استخدم Padding لضبط المسافات الداخلية.
  • القصّ والزوايا:
    عند عرض صور أو تأثيرات حبر داخل بطاقة بزوايا دائرية، عيّن clipBehavior: Clip.antiAlias على البطاقة (أو لفّ محتواها بـ ClipRRect بنفس نصف القطر).
  • متى أستخدم Card مقابل Container؟
    • استخدم Card عندما تريد مظهر Material (ظل/ارتفاع/تفاعل حبر).
    • استخدم Container إذا كان المطلوب فقط تباعد/لون/حدود بدون دلالات Material.
  • التوحيد عبر التطبيق:
    استخدم CardTheme داخل ThemeData لضبط شكل/ارتفاع/لون موحّد لكل البطاقات: dartCopyEditMaterialApp( theme: ThemeData( cardTheme: CardTheme( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), margin: const EdgeInsets.all(8), clipBehavior: Clip.antiAlias, ), ), home: ... )
خلاصة
  • Card تعطيك حاوية Material أنيقة بظلال وزوايا دائرية.
  • خصائصها الأساسية: elevation, shape, margin, color, surfaceTintColor, clipBehavior, وchild.
  • اجعلها تفاعلية بإضافة InkWell/InkResponse داخلها.
  • اهتم بالأداء والتصميم باستعمال خصائص Material 3 وCardTheme.