تخطَّ إلى المحتوى

الـ Widgets الأساسية في Flutter

الدرس 3 من 33 · Flutter

تعلمت أن كل شيء في Flutter Widget، وأن الشاشة شجرة من الـ Widgets داخل بعضها. في هذا الدرس ستتعرف على القطع الأساسية التي ستستخدمها في كل شاشة تقريباً: النصوص، والصناديق، والمسافات، والأيقونات، والصور. وفي النهاية ستركّبها معاً لتبني بطاقة تعريف شخصية جميلة.

const Text(
'سارة أحمد',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Colors.indigo,
),
)
  • المعامل الأول (بالموضع) هو النص نفسه.
  • style يستقبل TextStyle فيه: fontSize للحجم، و fontWeight للسمك، و color للون.
  • textAlign: TextAlign.center لتوسيط النص إذا امتد على أكثر من سطر.

لاحظ أن الأسلوب يشبه CSS كثيراً، لكنه مكتوب بـ Dart وبمعاملات مسماة.

Container: الصندوق متعدد المواهب

Section titled “Container: الصندوق متعدد المواهب”

Container أكثر Widget مرونة: صندوق يمكن أن يكون له حجم ومسافات ولون وإطار وزوايا دائرية:

Container(
width: 280,
padding: const EdgeInsets.all(20),
margin: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.indigo.shade50,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.indigo, width: 2),
),
child: const Text('محتوى الصندوق'),
)
  • padding: مسافة داخلية بين الإطار والمحتوى.
  • margin: مسافة خارجية حول الصندوق.
  • decoration: الشكل: اللون، والزوايا الدائرية، والإطار، وحتى الظل والتدرج.
  • child: الـ Widget الموجود داخل الصندوق.

إذا درست CSS، ستلاحظ أن هذا هو نموذج الصندوق نفسه تقريباً. وإذا لم تدرسه، تخيّل Container مثل علبة هدايا: لها حجم، وورق تغليف ملون، ومسافة بين الهدية وجدار العلبة.

EdgeInsets.all(16) // من كل الجهات
EdgeInsets.symmetric(horizontal: 16, vertical: 8) // أفقي ورأسي
EdgeInsets.only(top: 12) // جهة واحدة

إذا احتجت مسافة فقط دون لون أو إطار، فلا داعي لـ Container:

const Padding(
padding: EdgeInsets.only(top: 12),
child: Text('أحب البرمجة والرسم'),
)
const SizedBox(height: 12) // فراغ رأسي بين عنصرين

SizedBox بدون child هي أبسط طريقة لوضع فراغ بين عنصرين، وستستخدمها كثيراً جداً.

const Icon(Icons.account_circle, size: 72, color: Colors.indigo)

Icons فيها آلاف أيقونات Material الجاهزة. ابحث عن أي أيقونة باسمها الإنجليزي في موقع Material Icons، أو اكتب Icons. في المحرر واستعرض الاقتراحات.

Image.network('https://dummyjson.com/image/300x200', width: 300)
Image.asset('assets/images/logo.png', width: 120)
  • Image.network: صورة من الإنترنت برابطها.
  • Image.asset: صورة من ملفات تطبيقك. لكن يجب أولاً أن تخبر Flutter بمكانها في pubspec.yaml:
pubspec.yaml
flutter:
assets:
- assets/images/

انتبه للمسافات في بداية الأسطر في ملف pubspec.yaml، فهي جزء من الصيغة، وأي خطأ فيها يمنع ظهور الصور.

سترى في المثال القادم Center الذي يضع ابنه في منتصف المساحة المتاحة، و Column الذي يرتب عدة أبناء فوق بعضهم عبر الخاصية children (قائمة وليس ابناً واحداً). سنشرح Column وأخاه Row بالتفصيل في درس قادم.

لاحظ الفرق المهم: أغلب الـ Widgets تأخذ ابناً واحداً في child، والقليل مثل Column و Row تأخذ قائمة في children.

المشروع: بطاقة تعريف شخصية

Section titled “المشروع: بطاقة تعريف شخصية”
lib/main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(home: ProfileCard()));
}
class ProfileCard extends StatelessWidget {
const ProfileCard({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
width: 280,
padding: const EdgeInsets.all(20),
margin: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.indigo.shade50,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: Colors.indigo, width: 2),
),
child: const Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.account_circle, size: 72, color: Colors.indigo),
SizedBox(height: 12),
Text(
'سارة أحمد',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Colors.indigo,
),
),
SizedBox(height: 4),
Text('مطورة تطبيقات مبتدئة'),
Padding(
padding: EdgeInsets.only(top: 12),
child: Text(
'أحب البرمجة والرسم',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.black54),
),
),
],
),
),
),
);
}
}

النتيجة: بطاقة بنفسجية فاتحة بإطار وزوايا دائرية في منتصف الشاشة، فيها أيقونة شخص كبيرة، ثم الاسم بخط عريض، ثم الوصف. و mainAxisSize: MainAxisSize.min تجعل العمود بارتفاع محتواه فقط بدلاً من أن يملأ الشاشة.

اقرأ الكود كشجرة: Scaffold ← Center ← Container ← Column ← (أيقونة، مسافة، نص، مسافة، نص، Padding ← نص).

  1. شغّل بطاقة التعريف، ثم ضع اسمك ووصفك.
  2. غيّر لون البطاقة إلى Colors.teal.shade50 والإطار إلى Colors.teal.
  3. أضف صفاً من المعلومات تحت الوصف: أيقونة Icons.location_on ونص المدينة (ضعهما مؤقتاً فوق بعضهما).
  4. تحدٍّ: أضف ظلاً للبطاقة بالخاصية boxShadow داخل BoxDecoration.
  • child مع Column: Column تأخذ children (قائمة)، وليس child.
  • color و decoration معاً في Container: يسبب خطأ. ضع اللون داخل BoxDecoration.
  • صورة asset لا تظهر: نسيت تسجيل المجلد في pubspec.yaml، أو أن المسار والاسم لا يطابقان الملف حرفياً.

سؤال

ما الفرق بين padding و margin في Container؟

سؤال

ما أبسط طريقة لوضع فراغ رأسي 16 بين عنصرين في عمود؟

  • Text و TextStyle لعرض النصوص بالحجم والسمك واللون.
  • Container صندوق بحجم و padding و margin و decoration للون والزوايا والإطار.
  • Padding و SizedBox للمسافات فقط، و EdgeInsets لتحديدها.
  • Icon من مكتبة Icons، و Image.network و Image.asset للصور مع تسجيلها في pubspec.yaml.
  • أغلب الـ Widgets تأخذ child واحداً، و Column و Row تأخذان children.