مبتدئ → تطبيقي · 10 دروس

Flutter — تطبيقات موبايل من الصفر

تبني تطبيقاً واحداً يعمل على Android و iOS: واجهات عربية، شاشات، حالة، وربط API — وتخرج بـ MVP قابل للعرض أو التطوير مع فريق MesueTech.

كيف تدرس هذا المسار؟

  1. اقرأ الدرس وافهم المفهوم قبل الكود.
  2. انسخ أمثلة Dart وجرّبها في مشروعك.
  3. استخدم flutter doctor و Hot Reload.
  4. سجّل إكمال كل درس — التقدّم محلي.

محتوى أصلي من Mesue Learn — عملي ومناسب لسن +12 وما فوق.

1. لماذا Flutter؟ — تطبيق واحد، منصتان

الهدف: تميّز بين تطبيق ويب وتطبيق موبايل أصلي ومتعدد المنصات.

تطبيق الموبايل يُثبَّت من المتجر ويستخدم كاميرا، إشعارات، وعملاً أسرع أحياناً من موقع.

Flutter إطار من Google: تكتب Dart مرة واحدة → تطبيق Android + iOS (+ ويب لاحقاً).

مقارنة سريعة:
• موقع ويب: سهل الوصول، لا متجر
• Flutter: تجربة موبايل كاملة، متجر، أوفلاين جزئي

Mesue مثال: منتج HLO بدأ بمكالمات وإشعارات — MVP صغير أولاً.

قاعدة: 3 شاشات + ميزة واحدة أساسية = إصدار 1.0 معقول.

  • Flutter = Dart + Widgets + محرك رسم سريع
  • كود واحد لمنصتين يوفر وقت الفرق الصغير
  • MVP صغير قبل ميزات ضخمة
  • يتكامل مع مسارات الويب و Git لاحقاً

صورة ذهنية

 [فكرة التطبيق]
        |
        v
   [كود Dart]
    /        \
   v          v
Android    iOS

مختبر: خريطة التطبيق

ارسم 3 مربعات للشاشات وأسهم الانتقال — ورقة أو Figma مجاني.

مهمة عملية

اكتب فقرة: لماذا تطبيق موبايل أفضل من موقع لتطبيقك؟

اختبر فهمك

Flutter يتيح أساساً...

2. التثبيت — Flutter SDK وأدوات التطوير

الهدف: تثبّت Flutter وتتحقق بـ flutter doctor.

1) حمّل Flutter من flutter.dev/docs/get-started
2) أضف flutter/bin لـ PATH
3) ثبّت Android Studio (للمحاكي) أو Xcode على Mac لـ iOS
4) في Terminal:
flutter doctor
flutter doctor --android-licenses

محرر: VS Code + امتداد Dart/Flutter أو Android Studio.

أول تشغيل قد يحمّل ملفات — انتظر.

على Windows: فعّل Developer Mode لـ symlink إن طُلب.

  • flutter doctor يكشف النواقص
  • محاكي Android أو جهاز حقيقي USB
  • dart --version مع flutter
  • لا تتخطى التراخيص على Android

صورة ذهنية

 flutter doctor
    |
 +--+--+--+--+
 v  v  v  v  v
SDK IDE emu lic

مختبر: علامة صح خضراء

أصلح أول خطأ أحمر يظهر في flutter doctor — غالباً Android licenses أو cmdline-tools.

مهمة عملية

التقط لقطة شاشة flutter doctor بدون أخطاء حرجة (تحذيرات صفراء مقبولة).

اختبر فهمك

أي أمر يفحص بيئة Flutter؟

3. أول مشروع — flutter create و Hot Reload

الهدف: تنشئ مشروعاً وتشغّله على المحاكي.

flutter create mesue_app
cd mesue_app
flutter run

هيكل مهم:
lib/main.dart — نقطة البداية
pubspec.yaml — الحزم والأصول

Hot Reload: اضغط r في Terminal أثناء التشغيل — تعديل فوري.
Hot Restart: R لإعادة كاملة.

غيّر في main.dart نص العنوان إلى عربي — شاهد التحديث فوراً.

  • lib/main.dart = البداية
  • pubspec.yaml = dependencies
  • flutter run يشغّل التطبيق
  • Hot Reload يسرّع التطوير

صورة ذهنية

 main.dart
     |
  runApp()
     |
 MaterialApp
     |
  HomeScreen

مختبر: غيّر النص

بدّل «أول تطبيق لي» باسمك — Hot Reload — لاحظ السرعة.

مهمة عملية

أنشئ mesue_app وشغّله — غيّر لون AppBar في Theme.

اختبر فهمك

ملف البداية الافتراضي في Flutter؟

4. Widgets والتخطيط — كل شيء Widget

الهدف: تستخدم Scaffold و Column و Row و Container.

في Flutter كل عنصر Widget: نص، زر، صف، عمود.

Scaffold: هيكل شاشة (AppBar, body, FAB)
Column: ترتيب عمودي
Row: ترتيب أفقي
Container: صندوق بحشو ولون وحجم

Padding و SizedBox للمسافات.

RTL: MaterialApp(localizationsDelegates..., locale: Locale('ar')) أو directionality في التصميم.

  • Composition: Widgets داخل Widgets
  • Column/Row مع MainAxisAlignment
  • Expanded يملأ المساحة المتبقية
  • const للأداء عندما لا تتغير القيم

صورة ذهنية

 Scaffold
 ├── AppBar
 └── Column
      ├── Text
      ├── Row
      └── Button

مختبر: بطاقة

لف Column داخل Container بلون خلفية وpadding 16 — شكل «بطاقة».

مهمة عملية

ابنِ شاشة ترحيب: عنوان + وصف + زر «ابدأ».

اختبر فهمك

لترتيب عناصر عمودياً تستخدم...

5. StatefulWidget — عندما تتغير الشاشة

الهدف: تدير حالة بسيطة: عدّاد، نموذج، قائمة.

StatelessWidget: لا يتغير بعد البناء.
StatefulWidget: له State يمكن setState(() { ... }).

مثال عدّاد:
int count = 0;
onPressed: () => setState(() => count++);

القاعدة: setState يخبر Flutter «أعد الرسم».

للمشاريع الأكبر لاحقاً: Provider أو Riverpod — لكن ابدأ بـ setState.

  • setState يحدّث الواجهة
  • State منفصل عن Widget class
  • لا setState داخل build مباشرة
  • ابدأ بسيطاً قبل إدارة حالة معقدة

صورة ذهنية

 [زر +]
     |
 setState
     |
 count++
     |
 [إعادة رسم]

مختبر: قائمة مهام

List<String> tasks — TextField + زر يضيف مهمة بـ setState.

مهمة عملية

ابنِ عدّاداً أو قائمة مهام بسيطة بـ StatefulWidget.

اختبر فهمك

لتحديث الواجهة بعد تغيير متغير تستخدم...

6. التنقل — Navigator وشاشات متعددة

الهدف: تنتقل بين شاشتين أو ثلاث بـ routes.

Navigator.push(context, MaterialPageRoute(builder: (_) => SecondPage()));
Navigator.pop(context); // رجوع

أو routes مسماة في MaterialApp:
routes: { '/': (_) => Home(), '/detail': (_) => Detail() }

نمط Mesue MVP:
• شاشة قائمة
• شاشة تفاصيل
• شاشة إعدادات بسيطة

مرّر بيانات: constructor أو arguments.

  • push يفتح، pop يرجع
  • كل شاشة Scaffold منفصل
  • AppBar leading: BackButton تلقائي أحياناً
  • 3 شاشات كحد أقصى للإصدار الأول

صورة ذهنية

 Home --push--> Detail
   ^              |
   +---- pop -----+

مختبر: 3 شاشات

Home → قائمة عناصر → Detail عند النقر.

مهمة عملية

أضف شاشة «إعدادات» بها Switch للوضع الداكن (حتى لو محلي فقط).

اختبر فهمك

للرجوع من شاشة مفتوحة بـ push؟

7. قوائم ونماذج — ListView و TextField

الهدف: تعرض قائمة قابلة للتمرير وتجمع إدخال المستخدم.

ListView.builder للقوائم الطويلة:
itemCount: items.length,
itemBuilder: (ctx, i) => ListTile(title: Text(items[i]))

TextField مع controller:
final ctrl = TextEditingController();
TextField(controller: ctrl, decoration: InputDecoration(labelText: 'الاسم'))

Form + GlobalKey<FormState> للتحقق:
validator: (v) => v!.isEmpty ? 'مطلوب' : null

لا تنس dispose() للـ controllers.

  • ListView.builder للأداء
  • ListTile جاهز للقوائم
  • TextEditingController للنماذج
  • dispose في State.dispose

صورة ذهنية

 ListView
  ├── ListTile
  ├── ListTile
  └── ListTile

 Form → TextField → validator

مختبر: نموذج تسجيل

Form بحقول اسم وبريد — زر يتحقق قبل الإرسال.

مهمة عملية

اعرض قائمة 5 منتجات وهمية بـ ListView.

اختبر فهمك

للقوائم الطويلة الأفضل أداءً...

8. ربط API — http و JSON

الهدف: تجلب بيانات من الإنترنت وتعرضها مع loading وخطأ.

في pubspec.yaml:
dependencies:
http: ^1.2.0

ثم:
import 'package:http/http.dart' as http;
import 'dart:convert';

final res = await http.get(Uri.parse('https://api.example.com/items'));
if (res.statusCode == 200) {
final data = jsonDecode(res.body);
}

استخدم FutureBuilder:
future: fetchItems(),
builder: (ctx, snap) {
if (snap.connectionState == ConnectionState.waiting) return CircularProgressIndicator();
if (snap.hasError) return Text('خطأ');
return ListView(...);
}

لا تضع API keys في الكود — استخدم env أو backend.

  • async/await للشبكة
  • FutureBuilder للواجهة
  • معالجة loading و error
  • لا أسرار في التطبيق المنشور

صورة ذهنية

 App → http.get → API
          |
       JSON
          |
     FutureBuilder
          |
       ListView

مختبر: اقتباس عشوائي

جرّب API مجاني — اعرض نصاً مع زر «اقتباس جديد».

مهمة عملية

اربط API عاماً (quotes أو users) بـ FutureBuilder.

اختبر فهمك

أين تضع مفتاح API السري؟

9. العربية و RTL — تجربة مستخدم محلية

الهدف: تضبط الاتجاه والخطوط والنصوص العربية.

MaterialApp(
locale: const Locale('ar'),
supportedLocales: const [Locale('ar'), Locale('en')],
// مع flutter_localizations للتقويم والأزرار
)

Directionality(textDirection: TextDirection.rtl, child: ...)

خط عربي: أضف في pubspec.yaml fonts ثم:
theme: ThemeData(fontFamily: 'Cairo')

اختبر: الأيقونات، محاذاة النص، لوحة المفاتيح العربية.

Mesue: التطبيقات العربية تحترم RTL من اليوم الأول.

  • locale: ar للواجهة
  • خطوط عربية واضحة (Cairo, Tajawal)
  • اختبر على جهاز حقيقي
  • نصوص قصيرة في الأزرار

صورة ذهنية

 RTL:  [زر] ← النص
 LTR:  Text → [btn]

مختبر: واجهة عربية كاملة

حوّل كل النصوص للعربية — راجع المحاذاة في Row.

مهمة عملية

طبّق خطاً عربياً و locale ar على مشروعك.

اختبر فهمك

للصفحات العربية الاتجاه الافتراضي...

10. المشروع النهائي — MVP جاهز للعرض

الهدف: تسلّم تطبيقاً بـ 3 شاشات + قائمة أو API + عربية.

المطلوب:
• 3 شاشات متصلة (قائمة، تفاصيل، إعدادات أو إضافة)
• StatefulWidget أو قائمة ديناميكية
• واجهة عربية RTL
• (اختياري) جلب بيانات من API
• README: كيف تشغّل flutter run
• لقطة شاشة GIF أو 3 صور

معيار النجاح:
✓ يعمل على محاكي أو جهاز
✓ لا crashes عند الفتح
✓ نصوص عربية واضحة
✓ git repo مع .gitignore

الخطوة التالية: flutter build apk أو TestFlight — مع فريق Mesue عند الحاجة.

  • MVP صغير أفضل من تطبيق ضخم نصف جاهز
  • README للمراجع والعملاء
  • لقطات شاشة للمحفظة
  • اربط بمسار Git لنشر الكود

صورة ذهنية

 [قائمة] → [تفاصيل]
      ↓
 [إعدادات]
      ↓
 README + screenshots

مختبر: عرض 3 دقائق

سجّل فيديو قصير: فتح التطبيق → التنقل → ميزة واحدة.

مهمة عملية

سلّم MVP + README + رفع على GitHub إن أمكن.

اختبر فهمك

أفضل إصدار أول لتطبيق مبتدئ؟

تطبيقك المصغّر جاهز للعرض

ارفع الكود على GitHub وشارك لقطات — أو اطلب فريق Mesue لنشر المتجر.