مقدمة
مرحبًا بكم في الدرس الشامل حول استخدام وتخصيص MaterialApp في تطبيقات Flutter. MaterialApp هو عنصر أساسي في تطوير تطبيقات Flutter، حيث يوفر واجهة المستخدم الأساسية والعديد من الميزات المهمة مثل إدارة التنقل، وتخصيص الثيم، وإعدادات التطبيق العامة.
خلال هذا الدرس، سنتعلم كيفية استخدام MaterialApp لإنشاء تطبيقات Flutter فعالة وجميلة، بالإضافة إلى فهم كيفية تخصيص المظهر وإدارة التنقل بين الشاشات. سنستكشف جميع المعلمات والميزات الهامة التي يقدمها MaterialApp، بالإضافة إلى انشاء تطبيقات جيدة .
لنبدأ الرحلة ونكتشف مدى قوة MaterialApp في تطوير تطبيقات Flutter الخاصة بك!
، MaterialApp هو واحد من أهم العناصر في بناء تطبيقات المواد (Material Design)، وهو عبارة عن واجهة تستخدم لتكوين وتحديد خصائص التطبيق بأكمله.
تعتبر MaterialApp عبارة عن واجهة رئيسية تحتوي على العديد من الخصائص والمعلومات التي تحدد سلوك التطبيق بما يتماشى مع تصميم الواجهات.
فيما يلي قائمة بجميع الخصائص المتاحة في MaterialApp في Flutter:
home: تحدد الشاشة الرئيسية للتطبيق.
routes: تحدد مخطط المسارات للتطبيق، حيث يمكن تعيين قوائم المسارات والشاشات المقابلة لها.
initialRoute: يحدد المسار الأولي الذي يتم تحميله عند تشغيل التطبيق.
onGenerateRoute: وظيفة تُستدعى عندما يُطلب التطبيق لتوليد مسار غير مُعرَّف.
navigatorKey: يستخدم للوصول إلى المفتاح (key) الخاص بالملاح (navigator) الذي يُدير المسارات في التطبيق.
navigatorObservers: قائمة من المراقبين (observers) لمراقبة التغييرات في الملاح (navigator)، مثل تسجيل الأحداث أو تحليل تتبع المستخدم.
builder: دالة لبناء القائمة السريعة (drawer) والقائمة العلوية (app bar) للتطبيق.
title: يحدد عنوان التطبيق.
onGenerateTitle: وظيفة تُستدعى لتوليد عنوان للتطبيق.
color: يحدد لون الثيم (theme) الافتراضي للتطبيق.
theme: يحدد سمات التصميم العامة للتطبيق، مثل الألوان والخطوط والزوايا.
locale: تحدد اللغة المستخدمة في التطبيق.
localizationsDelegates: قائمة من المفوضين (delegates) للمحليات (localizations) المستخدمة في التطبيق.
localeListResolutionCallback: وظيفة تُستدعى عند تحديد اللغة المستخدمة في التطبيق.
supportedLocales: قائمة من اللغات المعتمدة في التطبيق.
debugShowMaterialGrid: عرض شبكة المواد (Material grid) لتحليل وتصحيح التصميم.
showPerformanceOverlay: يعرض فوق الطبقة (overlay) أدوات الأداء لتحليل أداء التطبيق.
checkerboardRasterCacheImages: يعرض الصور بمربعات متقاطعة لمساعدة في تحليل وتصحيح أداء التطبيق.
checkerboardOffscreenLayers: يعرض الطبقات غير المرئية بمربعات متقاطعة لمساعدة في تحليل وتصحيح أداء التطبيق.
showSemanticsDebugger: يعرض فوق الطبقة (overlay) أدوات تصحيح للدلالة (semantics) لمساعدة في فحص صحة تصميم التطبيق.
هذه هي الخصائص الرئيسية التي يمكن تكوينها باستخدام MaterialApp في Flutter، والتي تسمح بتخصيص وتحديد سلوك التطبيق بشكل شامل.
خطوات بسيطة لشرح كيفية استخدام MaterialApp في تطوير تطبيق Flutter:
الخطوة 1: إضافة تبعيات Flutter:
تأكد من أنك قمت بتثبيت Flutter على جهازك وأن لديك محرر رموز مثل Visual Studio Code أو Android Studio مثبتًا.
الخطوة 2: إنشاء مشروع Flutter جديد:
نقم بإنشاء مشروع Flutter جديد باستخدام الأمر التالي في سطر الأوامر أو في الطرفية:
flutter create my_flutter_app
ثم نقم بالانتقال إلى دليل المشروع الذي تم إنشاؤه:
cd my_flutter_app
الخطوة 3: تعديل ملف pubspec.:
افتح ملف pubspec. في محرر النصوص وأضف تبعيات المكتبات التي تحتاجها، على سبيل المثال، إذا كنت تريد استخدام material package:
dependencies: flutter: sdk: flutter material: ^2.0.0
بعد ذلك، نقم بتحديث التبعيات باستخدام الأمر التالي في الطرفية:
flutter pub get
الخطوة 4: استخدام MaterialApp في main.dart:
افتح ملف main.dart في مجلد lib، واستبدل الشيفرة الموجودة بشيفرة تستخدم MaterialApp. قم بتكوين التطبيق كما يلي:
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'My Flutter App', theme: ThemeData( primarySwatch: Colors.blue, // يمكنك هنا تعيين سمات التصميم العامة للتطبيق ), home: MyHomePage(), ); } } class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('My Home Page'), ), body: Center( child: Text('Welcome to my Flutter app!'), ), ); } }
في هذا المثال:
تم إنشاء تطبيق Flutter بواسطة MyApp، والذي يستخدم MaterialApp.
تم تعيين عنوان للتطبيق باستخدام title.
تم تحديد الشاشة الرئيسية للتطبيق باستخدام home، والتي في هذه الحالة هي MyHomePage.
الخطوة 5: تشغيل التطبيق:
بعد إتمام الخطوات السابقة، قم بتشغيل التطبيق باستخدام الأمر التالي في الطرفية:
flutter run
بهذه الطريقة، يمكنك استخدام MaterialApp لبناء تطبيقات Flutter بشكل أساسي، ويمكنك تخصيص التطبيق بحسب احتياجاتك من خلال تكوين خصائص MaterialApp المختلفة.
شرح الكود :
في البداية، نستورد المكتبة material التي تحتوي على عناصر تصميم مواد Material Design.
import 'package:flutter/material.dart';
نقوم بتعريف دالة main() التي تعد نقطة البداية لتطبيق Flutter. تقوم هذه الدالة بتشغيل تطبيقنا باستخدام runApp() وتمرير كائن من MyApp.
void main() { runApp(MyApp()); }
تم تعريف الكلاس MyApp كـ StatelessWidget، والذي يمثل التطبيق نفسه. في هذا الكلاس، نقوم بتكوين MaterialApp.
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'My Flutter App', theme: ThemeData( primarySwatch: Colors.blue, // يمكنك هنا تعيين سمات التصميم العامة للتطبيق ), home: MyHomePage(), ); } }
داخل MaterialApp، نقوم بتحديد عنوان التطبيق باستخدام title ونحدد السمة العامة للتصميم باستخدام theme.
يتم تحديد الشاشة الرئيسية للتطبيق باستخدام home، حيث يتم تمرير كائن من MyHomePage.
كما هو موضح، يتم تعريف MyHomePage كـ StatelessWidget أيضًا، ويمثل الصفحة الرئيسية للتطبيق.
تظهر هنا شريط العنوان (AppBar) والمحتوى الأساسي للصفحة.
class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('My Home Page'), ), body: Center( child: Text('Welcome to my Flutter app!'), ), ); } }
في Scaffold، يمكننا تحديد شريط العنوان والمحتوى الأساسي للصفحة باستخدام appBar وbody على التوالي.
هذه هي الخطوات الرئيسية التي تمثل كيفية استخدام MaterialApp في تطوير تطبيقات Flutter.
تعتبر هذه الخطوات الأساسية للبدء في بناء تطبيقات Flutter باستخدام تصميم المواد.
MaterialApp هو العنصر الرئيسي في تطبيق Flutter ويحتوي على عدة مكونات أساسية. إليك قائمة بأهم مكونات MaterialApp:اشرح بالتفصيل تطبي على استخدام مكونات MaterialApp:
بالطبع! دعونا نشرح كيفية استخدام كل مكون من مكونات MaterialApp بالتفصيل:
title:
يُستخدم لتحديد عنوان التطبيق، ويظهر في العديد من الأماكن مثل شريط التطبيق وقائمة التطبيقات المفتوحة. يمكن استخدامه ببساطة كما يلي:
MaterialApp( title: 'My Flutter App', // باقي التكوينات هنا... )
theme:
يُستخدم لتحديد سمات التصميم العامة للتطبيق، مثل الألوان والخطوط والزوايا. يمكن تعيينه باستخدام ThemeData. على سبيل المثال:
MaterialApp( theme: ThemeData( primarySwatch: Colors.blue, fontFamily: 'Roboto', // باقي التكوينات هنا... ), )
home:
يُستخدم لتحديد الشاشة الرئيسية للتطبيق، حيث يتم عرضها عند تشغيل التطبيق. يمكن تعيينه ببساطة كما يلي:
MaterialApp( home: MyHomePage(), // باقي التكوينات هنا... )
routes:
يُستخدم لتحديد مخطط المسارات للتطبيق، حيث يمكن تعيين قوائم المسارات والشاشات المقابلة لها. يمكن تحديد المسارات مع الأسماء والدوال المُنشئة. مثال:
MaterialApp( routes: { '/': (context) => MyHomePage(), '/second': (context) => SecondScreen(), }, // باقي التكوينات هنا... )
initialRoute:
يُستخدم لتحديد المسار الأولي الذي يتم تحميله عند تشغيل التطبيق. يمكن تحديده بالطريقة التالية:
MaterialApp( initialRoute: '/second', // باقي التكوينات هنا... )
onGenerateRoute:
يُستخدم لتحديد دالة يُطلب تشغيلها عندما يُطلب المسار الذي لم يتم تحديده من قبل. يمكن استخدامه لتوليد المسارات ديناميكيًا. مثال:
MaterialApp( onGenerateRoute: (settings) { if (settings.name == '/third') { return MaterialPageRoute(builder: (context) => ThirdScreen()); } }, // باقي التكوينات هنا... )
navigatorKey:
يُستخدم للوصول إلى المفتاح الخاص بالملاح الذي يُدير المسارات في التطبيق. يمكن استخدامه كما يلي:
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); MaterialApp( navigatorKey: navigatorKey, // باقي التكوينات هنا... )
navigatorObservers:
يُستخدم لإضافة مراقبين (observers) لمراقبة التغييرات في الملاح (navigator)، مثل تسجيل الأحداث أو تحليل تتبع المستخدم. يمكن استخدامه كما يلي:
MaterialApp( navigatorObservers: [MyNavigatorObserver()], // باقي التكوينات هنا... )
builder:
يُستخدم لبناء القائمة السريعة (drawer) والقائمة العلوية (app bar) للتطبيق. يمكن استخدامه لتوسيع القائمة العلوية بواسطة AppBar أو إضافة القائمة الجانبية بواسطة Drawer. مثال:
MaterialApp( builder: (context, scaffold) { return Scaffold( appBar: AppBar( title: Text('My App'), ), drawer: Drawer( child: ListView( children: [ ListTile( title: Text('Item 1'), ), ListTile( title: Text('Item 2'), ), ], ), ), body: scaffold, ); }, // باقي التكوينات هنا... )
onGenerateTitle:
يُستخدم لتوليد عنوان للتطبيق، ويمكن استخدامه لتوفير عنوان ديناميكي استنادًا إلى الحالة الحالية للتطبيق. مثال:
MaterialApp( onGenerateTitle: (context) => 'My Dynamic App Title', // باقي التكوينات هنا... )
color:
يُستخدم لتحديد لون الثيم (theme) الافتراضي للتطبيق، ويمكن استخدامه لتحديد اللون الرئيسي للتطبيق. مثال:
MaterialApp( color: Colors.red, // باقي التكوينات هنا... )
هذه بعض المكونات الإضافية التي يمكن استخدامها في MaterialApp لتكوين وتخصيص تطبيقات Flutter. باستخدام هذه المكونات، يمكنك تعديل التطبيق بشكل كامل لتلبية متطلبات تصميم وسلوك التطبيق الخاص بك.
لنقم بإنشاء تطبيق بسيط يستخدم مكونات MaterialApp المذكورة مع شرح لكل جزء منها. سنقوم بإنشاء تطبيق يحتوي على شاشتين، الأولى هي الشاشة الرئيسية (HomeScreen) والثانية هي شاشة ثانوية (SecondScreen). سيكون للتطبيق شريط عنوان وسيتم تحميل الشاشات عبر استخدام المسارات.
قبل البدء، تأكد من أنك قمت بإضافة material package كتبعية في ملف pubspec..
الشرح سيتم داخل التعليقات في الشيفرة.
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( // 1. تحديد عنوان التطبيق title: 'MaterialApp Example', // 2. تحديد سمات التصميم العامة theme: ThemeData( primarySwatch: Colors.blue, ), // 3. تحديد الشاشة الرئيسية للتطبيق home: HomeScreen(), // 4. تحديد المسارات للشاشات routes: { '/second': (context) => SecondScreen(), }, ); } } // شاشة الصفحة الرئيسية class HomeScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Home Screen'), // عنوان شريط العنوان ), body: Center( child: ElevatedButton( onPressed: () { // 5. تحميل شاشة ثانوية عند النقر Navigator.pushNamed(context, '/second'); }, child: Text('Go to Second Screen'), // زر للانتقال إلى الشاشة الثانية ), ), ); } } // شاشة الصفحة الثانية class SecondScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Second Screen'), // عنوان شريط العنوان ), body: Center( child: ElevatedButton( onPressed: () { // 6. العودة إلى الشاشة الرئيسية عند النقر Navigator.pop(context); }, child: Text('Go back to Home Screen'), // زر للعودة إلى الشاشة الرئيسية ), ), ); } }
هذا التطبيق يقوم بتحميل شاشة ثانوية عند النقر على زر في الشاشة الرئيسية، ثم يمكنك العودة إلى الشاشة الرئيسية عند النقر على زر في الشاشة الثانية. كل جزء من المكونات المستخدمة في MaterialApp تم توضيحه بالتعليقات في الشيفرة.
شجر ويدجيتات هذا التطبيق
بالطبع! سأقوم بكتابة شجرة التطبيق والويدجتات المستخدمة في التطبيق الذي قمت بشرحه سابقًا:
MaterialApp └─ HomeScreen └─ Scaffold ├─ AppBar │ └─ Text (title: 'Home Screen') └─ Center └─ ElevatedButton ├─ onPressed: Navigator.pushNamed(context, '/second') └─ Text (child: 'Go to Second Screen') └─ SecondScreen └─ Scaffold ├─ AppBar │ └─ Text (title: 'Second Screen') └─ Center └─ ElevatedButton ├─ onPressed: Navigator.pop(context) └─ Text (child: 'Go back to Home Screen')
هذه الشجرة تمثل التنظيم الهرمي للتطبيق والويدجتات المستخدمة في كل شاشة. تظهر كل شاشة تحت MaterialApp، وتحتوي على واجهة مستخدم مواد Scaffold التي تتضمن AppBar و Center، والتي بدورها تحتوي على الويدجتات الأخرى مثل الأزرار والنصوص.
دعنا نقوم بإنشاء تطبيق أكثر شمولية يستخدم مكونات MaterialApp بشكل مفصل. سنقوم بإنشاء تطبيق يحتوي على العديد من المكونات والوظائف المختلفة التي يوفرها MaterialApp.
سنقوم بإنشاء تطبيق يحتوي على العناصر التالية:
شريط عنوان مخصص.
قائمة جانبية (Drawer).
شاشة رئيسية.
استخدام الألوان المخصصة والخطوط.
تطبيق موضوع مخصص.
تنقل بين الشاشات باستخدام المسارات.
استخدام اللغات المتعددة.
مراقبة التلاعب بالشاشة (Screen Manipulation).
عرض أدوات الأداء (Performance Tools).
لنقم بكتابة التطبيق وشرح استخدام كل مكون:
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( // 1. تحديد عنوان التطبيق title: 'Comprehensive MaterialApp App', // 2. تحديد سمات التصميم العامة theme: ThemeData( primarySwatch: Colors.blue, fontFamily: 'Roboto', ), // 3. تحديد الشاشة الرئيسية للتطبيق home: HomeScreen(), // 4. تحديد المسارات للشاشات routes: { '/second': (context) => SecondScreen(), '/third': (context) => ThirdScreen(), }, // 5. استخدام اللغات المتعددة supportedLocales: [ const Locale('en', 'US'), const Locale('ar', 'SA'), ], // 6. تحديد الموضوع المخصص builder: (context, child) { return Directionality( textDirection: TextDirection.rtl, child: Builder( builder: (BuildContext context) { return Theme( data: ThemeData( primaryColor: Colors.deepPurple, // لون أساسي مخصص accentColor: Colors.deepOrangeAccent, // لون ثانوي مخصص fontFamily: 'Roboto', // خط مخصص ), child: child!, ); }, ), ); }, // 7. عرض أدوات الأداء debugShowCheckedModeBanner: false, showPerformanceOverlay: true, ); } } // شاشة الصفحة الرئيسية class HomeScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Home Screen'), // عنوان شريط العنوان ), // 8. استخدام الألوان المخصصة والخطوط body: Center( child: Text( 'Welcome to the Home Screen!', style: TextStyle( color: Theme.of(context).primaryColor, fontSize: 24.0, fontWeight: FontWeight.bold, ), ), ), // 9. قائمة جانبية (Drawer) drawer: Drawer( child: ListView( padding: EdgeInsets.zero, children: [ DrawerHeader( child: Text('Drawer Header'), decoration: BoxDecoration( color: Colors.blue, ), ), ListTile( title: Text('Second Screen'), onTap: () { Navigator.popAndPushNamed(context, '/second'); }, ), ListTile( title: Text('Third Screen'), onTap: () { Navigator.popAndPushNamed(context, '/third'); }, ), ], ), ), ); } } // شاشة الصفحة الثانية class SecondScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Second Screen'), // عنوان شريط العنوان ), body: Center( child: Text( 'This is the Second Screen!', style: TextStyle( color: Theme.of(context).accentColor, fontSize: 24.0, fontWeight: FontWeight.bold, ), ), ), ); } } // شاشة الصفحة الثالثة class ThirdScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Third Screen'), // عنوان شريط العنوان ), body: Center( child: Text( 'This is the Third Screen!', style: TextStyle( color: Theme.of(context).accentColor, fontSize: 24.0, fontWeight: FontWeight.bold, ), ), ), ); } }
هذا التطبيق يستخدم العديد من مكونات MaterialApp بشكل مفصل، بدءًا من تحديد العنوان وسمات التصميم العامة والشاشة الرئيسية والمسارات والموضوع المخصص واللغات المتعددة وأدوات الأداء وغيرها. كل مكون يوفر وظيفة محددة لتخصيص وتحسين التطبيق بشكل كامل.
الكود في اسطر منفصلة
سأقوم بشرح الكود في أسطر منفصلة:
استيراد مكتبة material التي تحتوي على عناصر تصميم مواد Material Design.
import 'package:flutter/material.dart';
إنشاء دالة main() التي تعتبر نقطة البداية لتطبيق Flutter وتشغيل التطبيق باستخدام runApp() وتمرير كائن من MyApp.
void main() { runApp(MyApp()); }
إنشاء كلاس MyApp الذي يرث من StatelessWidget ويمثل التطبيق نفسه.
class MyApp extends StatelessWidget {
تنفيذ دالة build() لإرجاع MaterialApp وتحديد العنوان وسمات التصميم العامة والشاشة الرئيسية والمسارات والموضوع المخصص واللغات المتعددة وأدوات الأداء.
@override Widget build(BuildContext context) { return MaterialApp( title: 'Comprehensive MaterialApp App', theme: ThemeData( primarySwatch: Colors.blue, fontFamily: 'Roboto', ), home: HomeScreen(), routes: { '/second': (context) => SecondScreen(), '/third': (context) => ThirdScreen(), }, supportedLocales: [ const Locale('en', 'US'), const Locale('ar', 'SA'), ], builder: (context, child) { return Directionality( textDirection: TextDirection.rtl, child: Builder( builder: (BuildContext context) { return Theme( data: ThemeData( primaryColor: Colors.deepPurple, accentColor: Colors.deepOrangeAccent, fontFamily: 'Roboto', ), child: child!, ); }, ), ); }, debugShowCheckedModeBanner: false, showPerformanceOverlay: true, ); }
إنشاء شاشة الصفحة الرئيسية HomeScreen التي تستخدم Scaffold وتحتوي على شريط عنوان مخصص وقائمة جانبية.
class HomeScreen extends StatelessWidget {
إنشاء شاشات الصفحات الثانية والثالثة SecondScreen وThirdScreen التي تستخدم Scaffold وتحتوي على شريط عنوان مخصص.
class SecondScreen extends StatelessWidget {
class ThirdScreen extends StatelessWidget {
هذا الشرح يعطي لمحة عامة عن الكود ويشرح كل جزء منه بشكل مفصل.
شجرة الويدجتات لهذا التطبيق
MaterialApp └─ HomeScreen └─ Scaffold ├─ AppBar │ └─ Text (title: 'Home Screen') ├─ Center │ └─ Text (Welcome message) └─ Drawer ├─ DrawerHeader │ └─ Text ('Drawer Header') └─ ListView ├─ ListTile (Navigate to Second Screen) └─ ListTile (Navigate to Third Screen) └─ SecondScreen └─ Scaffold ├─ AppBar │ └─ Text (title: 'Second Screen') └─ Center └─ Text ('This is the Second Screen!') └─ ThirdScreen └─ Scaffold ├─ AppBar │ └─ Text (title: 'Third Screen') └─ Center └─ Text ('This is the Third Screen!')
هذه الشجرة توضح تنظيم وتركيب الويدجتات في التطبيق، حيث يتكون التطبيق من الشاشة الرئيسية HomeScreen وشاشات فرعية SecondScreen و ThirdScreen. كل شاشة تحتوي على Scaffold، والذي يحتوي بدوره على AppBar والمحتوى الرئيسي للشاشة مثل النصوص أو الأزرار. توجد أيضًا قائمة جانبية (Drawer) في الشاشة الرئيسية تحتوي على عناصر القائمة للتنقل بين الشاشات.
لنقم بإنشاء تطبيق أكثر شمولية يستخدم مكونات MaterialApp بشكل شامل. سنقوم بتطبيق يتضمن العديد من العناصر والوظائف المختلفة التي يوفرها MaterialApp، بما في ذلك:
استخدام الموضوعات المخصصة.
تحديد المسارات وتنقل بين الشاشات.
استخدام اللغات المتعددة.
استخدام قائمة التنقل الجانبية (Drawer).
استخدام المراقبين (Observers).
استخدام واجهة المستخدم المتجاوبة.
تخصيص الألوان والخطوط.
استخدام أدوات تحسين الأداء.
سنقوم ببناء تطبيق يعرض قائمة من المنتجات، ويتيح للمستخدم التنقل بين شاشات المنتجات وشاشة التفاصيل، وكذلك استخدام الثيم المخصص واللغات المتعددة والمزيد.
لنبدأ بكتابة الكود:
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Comprehensive MaterialApp App', // 1. استخدام الموضوعات المخصصة theme: ThemeData( primarySwatch: Colors.blue, fontFamily: 'Roboto', ), // 2. تحديد المسارات وتنقل بين الشاشات initialRoute: '/', routes: { '/': (context) => ProductsScreen(), '/product_detail': (context) => ProductDetailScreen(), }, // 3. استخدام اللغات المتعددة supportedLocales: [ const Locale('en', 'US'), const Locale('ar', 'SA'), ], // 4. استخدام قائمة التنقل الجانبية (Drawer) drawer: AppDrawer(), // 5. استخدام المراقبين (Observers) navigatorObservers: [MyNavigatorObserver()], // 6. استخدام واجهة المستخدم المتجاوبة builder: (context, child) { return ResponsiveWrapper( child: child!, ); }, // 7. تخصيص الألوان والخطوط color: Colors.red, // 8. استخدام أدوات تحسين الأداء debugShowCheckedModeBanner: false, showPerformanceOverlay: true, ); } } class MyNavigatorObserver extends NavigatorObserver { // Implement observer methods as needed } class ResponsiveWrapper extends StatelessWidget { final Widget child; const ResponsiveWrapper({Key? key, required this.child}) : super(key: key); @override Widget build(BuildContext context) { // Implement responsive UI logic return child; } } class AppDrawer extends StatelessWidget { @override Widget build(BuildContext context) { return Drawer( child: ListView( padding: EdgeInsets.zero, children: [ DrawerHeader( child: Text('App Drawer'), decoration: BoxDecoration( color: Colors.blue, ), ), ListTile( title: Text('Home'), onTap: () { Navigator.popAndPushNamed(context, '/'); }, ), ListTile( title: Text('Settings'), onTap: () { Navigator.popAndPushNamed(context, '/settings'); }, ), ], ), ); } } class ProductsScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Products'), ), body: ListView( children: [ ListTile( title: Text('Product 1'), onTap: () { Navigator.pushNamed(context, '/product_detail'); }, ), ListTile( title: Text('Product 2'), onTap: () { Navigator.pushNamed(context, '/product_detail'); }, ), ], ), ); } } class ProductDetailScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Product Detail'), ), body: Center( child: Text('Product Detail'), ), ); } }
هذا التطبيق يشمل العديد من مكونات MaterialApp بشكل شامل. يوفر تحكمًا كاملاً في تصميم التطبيق وتوفير تجربة مستخدم متعددة اللغات ومراقبة للتنقل وتخصيص الثيمات واستخدام أدوات تحسين الأداء والمزيد.
شرح الكود سطرا بعد سطر :
استيراد مكتبة material التي تحتوي على عناصر تصميم مواد Material Design.
import 'package:flutter/material.dart';
إنشاء دالة main() التي تعتبر نقطة البداية لتطبيق Flutter وتشغيل التطبيق باستخدام runApp() وتمرير كائن من MyApp.
void main() { runApp(MyApp()); }
إنشاء كلاس MyApp الذي يرث من StatelessWidget ويمثل التطبيق نفسه.
dart
class MyApp extends StatelessWidget {
تنفيذ دالة build() لإرجاع MaterialApp وتحديد العنوان وسمات التصميم العامة والشاشة الرئيسية والمسارات واللغات المتعددة والقائمة الجانبية والمراقبين وواجهة المستخدم المتجاوبة وتخصيص الألوان والخطوط وأدوات تحسين الأداء.
@override Widget build(BuildContext context) { return MaterialApp( title: 'Comprehensive MaterialApp App', theme: ThemeData( primarySwatch: Colors.blue, fontFamily: 'Roboto', ), initialRoute: '/', routes: { '/': (context) => ProductsScreen(), '/product_detail': (context) => ProductDetailScreen(), }, supportedLocales: [ const Locale('en', 'US'), const Locale('ar', 'SA'), ], drawer: AppDrawer(), navigatorObservers: [MyNavigatorObserver()], builder: (context, child) { return ResponsiveWrapper( child: child!, ); }, color: Colors.red, debugShowCheckedModeBanner: false, showPerformanceOverlay: true, ); }
إنشاء كلاس MyNavigatorObserver الذي يرث من NavigatorObserver ويمثل المراقب للتنقل.
class MyNavigatorObserver extends NavigatorObserver { // Implement observer methods as needed }
إنشاء كلاس ResponsiveWrapper الذي يرث من StatelessWidget ويمثل واجهة المستخدم المتجاوبة.
class ResponsiveWrapper extends StatelessWidget { final Widget child; const ResponsiveWrapper({Key? key, required this.child}) : super(key: key); @override Widget build(BuildContext context) { // Implement responsive UI logic return child; } }
إنشاء كلاس AppDrawer الذي يرث من StatelessWidget ويمثل القائمة الجانبية للتطبيق.
class AppDrawer extends StatelessWidget { @override Widget build(BuildContext context) { return Drawer( child: ListView( padding: EdgeInsets.zero, children: [ DrawerHeader( child: Text('App Drawer'), decoration: BoxDecoration( color: Colors.blue, ), ), ListTile( title: Text('Home'), onTap: () { Navigator.popAndPushNamed(context, '/'); }, ), ListTile( title: Text('Settings'), onTap: () { Navigator.popAndPushNamed(context, '/settings'); }, ), ], ), ); } }
إنشاء كلاس ProductsScreen الذي يرث من StatelessWidget ويمثل شاشة الصفحة الرئيسية التي تعرض قائمة المنتجات.
class ProductsScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Products'), ), body: ListView( children: [ ListTile( title: Text('Product 1'), onTap: () { Navigator.pushNamed(context, '/product_detail'); }, ), ListTile( title: Text('Product 2'), onTap: () { Navigator.pushNamed(context, '/product_detail'); }, ), ], ), ); } }
إنشاء كلاس ProductDetailScreen الذي يرث من StatelessWidget ويمثل شاشة عرض تفاصيل المنتج.
class ProductDetailScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Product Detail'), ), body: Center( child: Text('Product Detail'), ), ); } }
هذا الشرح يساعدك على فهم الكود بشكل أفضل بتقسيمه إلى أجزاء منفصلة مع شرح لكل جزء.
شجرة الويدجتات للتطبيق الشامل:
MaterialApp └─ MyNavigatorObserver └─ ResponsiveWrapper └─ AppDrawer └─ Drawer └─ DrawerHeader └─ ListView ├─ ListTile (Home) └─ ListTile (Settings) └─ Navigator (تحتوي على الشاشة الحالية والتي يتم تحديدها بالمسار) ├─ ProductsScreen │ └─ Scaffold │ ├─ AppBar │ └─ ListView │ ├─ ListTile (Product 1) │ └─ ListTile (Product 2) └─ ProductDetailScreen └─ Scaffold ├─ AppBar └─ Center └─ Text ('Product Detail')
هذه الشجرة توضح تنظيم الويدجتات في التطبيق، بدءًا من المكونات الجذرية MaterialApp والمراقبين وواجهة المستخدم المتجاوبة، مرورًا بقائمة التنقل الجانبية وشاشات المنتجات وشاشة تفاصيل المنتج.
سنقوم بإنشاء تطبيق “Quiz App” باستخدام MaterialApp. هذا التطبيق سيتيح للمستخدمين الإجابة على أسئلة متعددة الاختيارات وعرض النتائج في النهاية.
لنبدأ بتصميم الكويز:
البيانات:
سنستخدم قائمة من الأسئلة، حيث يتكون كل سؤال من النص السؤال وقائمة من الخيارات والإجابة الصحيحة.
الشاشات:
شاشة البداية: تعرض زر لبدء الكويز.
شاشة السؤال: تعرض السؤال والخيارات وزر للانتقال إلى السؤال التالي.
شاشة النتيجة: تعرض نتيجة الكويز مع عدد الأسئلة الصحيحة.
المواد:
MaterialApp لتضمين التطبيق.
Scaffold لتخطيط الشاشات.
AppBar لشريط العنوان.
Navigator لإدارة تنقل الشاشات.
ListView لعرض الأسئلة والخيارات.
ElevatedButton للأزرار.
Text لعرض النص.
لنقم بكتابة الكود:
import 'package:flutter/material.dart'; void main() { runApp(QuizApp()); } class QuizApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Quiz App', home: QuizStartScreen(), ); } } class QuizStartScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Quiz App'), ), body: Center( child: ElevatedButton( onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => QuizScreen()), ); }, child: Text('Start Quiz'), ), ), ); } } class QuizScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Quiz'), ), body: ListView( children: [ ListTile( title: Text('Question 1'), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Option 1'), Text('Option 2'), Text('Option 3'), ], ), ), ElevatedButton( onPressed: () { // Handle answer submission }, child: Text('Next Question'), ), ], ), ); } } class QuizResultScreen extends StatelessWidget { final int score; final int totalQuestions; QuizResultScreen({required this.score, required this.totalQuestions}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Quiz Result'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('You scored $score out of $totalQuestions'), ElevatedButton( onPressed: () { // Reset quiz or navigate to start screen }, child: Text('Try Again'), ), ], ), ), ); } }
هذا التطبيق يعرض شاشة بداية الكويز، وبمجرد النقر على زر “بدء الكويز”، يتم نقل المستخدم إلى شاشة السؤال حيث يمكنه الإجابة على الأسئلة والانتقال إلى السؤال التالي. في النهاية، يتم عرض شاشة النتيجة مع النتيجة النهائية.
سنقوم بإنشاء اختبار قصير يتضمن أسئلة حول فهم المفاهيم التي تم شرحها في هذا الدرس. سنقدم بعض الأسئلة ويتوجب عليك الإجابة عليها. هيا نبدأ:
تقديم السمات المرئية للتطبيق
تقديم القوالب للشاشات
إنشاء نقطة بداية للتطبيق وتحديد الإعدادات العامة مثل اللغة والموضوع والمسارات
إنشاء أزرار التنقل في التطبيق
عنوان التطبيق
عنوان الصفحة الحالية
عنوان السمة الافتراضية
عنوان الزر الذي يتم النقر عليه
HomeScreen
StartScreen
MainScreen
InitialScreen
باستخدام initialPath
باستخدام routes
باستخدام navigateTo
باستخدام setPath
عرض القوالب
إدارة التنقل بين الشاشات
تطبيق الثيمات
التحكم في التنقل على مستوى الراوت
وظيفة تسجيل أداء التطبيق
وظيفة مراقبة حالة الاتصال بالإنترنت
وظيفة مراقبة التنقل بين الشاشات
وظيفة مراقبة حدوث الأخطاء في التطبيق
باستخدام ThemeData
باستخدام MaterialTheme
باستخدام AppStyle
باستخدام DesignTheme
لتحديد اللغة الافتراضية
لتحديد اللغات المدعومة للترجمة
لتحديد اللغة الثانوية للتطبيق
لتحديد اللغات التي يتم ترجمة النصوص إليها
إظهار أو إخفاء شعار التطوير
تمكين أو تعطيل وضع التطوير
إظهار أو إخفاء شاشة التحقق
تمكين أو تعطيل وضع التحقق من الأمان
عرض تحليل الأداء
تمكين واجهة المستخدم القياسية
عرض نافذة مراقبة الأداء
تمكين وضع الأداء العالي
تشييد واجهة المستخدم الرئيسية للتطبيق
تحديد القوالب المستخدمة في التطبيق
تخصيص المواد المستخدمة في التطبيق
إنشاء واجهة المستخدم بناءً على السمات المحددة
إنشاء درج يمكن الوصول إليه من أي شاشة في التطبيق
تعريف قائمة جانبية يمكن فتحها من أي شاشة في التطبيق
تحديد التصميم العام للتطبيق بالكامل
إضافة خيارات تحرير إلى شريط العنوان للتطبيق
تسجيل المراقبين لمراقبة التنقل بين الشاشات
تحديد الملاحظات التي يتم عرضها على الشاشات
تسجيل المراقبين لتحليل أداء التطبيق
تحديد الإشعارات التي يتم إرسالها إلى المستخدم
باستخدام MaterialTheme
باستخدام DesignTheme
باستخدام ThemeData
باستخدام AppTheme
تحديد الشاشة التي يتم عرضها أولاً عند بدء التطبيق
تحديد الشاشة التي يتم عرضها عند الانتقال من الشاشة الحالية
تحديد المسار الافتراضي الذي يتم تحميله عند بدء التطبيق
تحديد العرض الأولي الذي يظهر للمستخدم عند فتح التطبيق
عرض مؤشر أداء في الزاوية اليمنى العلوية للتطبيق
عرض إشعارات الأداء للمستخدم
تمكين واجهة المستخدم المتجاوبة لتحسين الأداء
تحديد مستوى أداء التطبيق
الاجابات
ما هي وظيفة MaterialApp في تطبيق Flutter؟
إنشاء نقطة بداية للتطبيق وتحديد الإعدادات العامة مثل اللغة والموضوع والمسارات
ما الذي يمثله المعلمة title في MaterialApp؟
عنوان التطبيق
ما هو الشاشة التي تُعرض عند بدء التطبيق؟
HomeScreen
كيف يمكنك تحديد المسارات في MaterialApp؟
باستخدام routes
ما هو دور Navigator في Flutter؟
إدارة التنقل بين الشاشات
ما هي المراقبات (Observers) في Flutter؟
وظيفة مراقبة حدوث الأخطاء في التطبيق
كيف يمكن تخصيص المظهر العام للتطبيق في Flutter؟
باستخدام ThemeData
ما هو استخدام supportedLocales في MaterialApp؟
لتحديد اللغات المدعومة للترجمة
ما هو استخدام debugShowCheckedModeBanner في MaterialApp؟
إظهار أو إخفاء شعار التطوير
ما هو استخدام showPerformanceOverlay في MaterialApp؟
عرض مؤشر أداء في الزاوية اليمنى العلوية للتطبيق
ما هو دور builder في MaterialApp؟
تحديد الملاحظات التي يتم عرضها على الشاشات
ما هي وظيفة drawer في MaterialApp؟
تعريف قائمة جانبية يمكن فتحها من أي شاشة في التطبيق
ما هو استخدام navigatorObservers في MaterialApp؟
تسجيل المراقبين لمراقبة التنقل بين الشاشات
كيف يمكن تخصيص الثيم الافتراضي للتطبيق في MaterialApp؟
باستخدام ThemeData
ما هو استخدام initialRoute في MaterialApp؟
تحديد الشاشة التي يتم عرضها أولاً عند بدء التطبيق
ما هو دور showPerformanceOverlay في MaterialApp؟
عرض مؤشر أداء في الزاوية اليمنى العلوية للتطبيق