مقدمة:
في هذا الدرس، سنتعرف على كيفية استخدام وتعريف PopupMenuButton في تطبيقات Flutter. يعد PopupMenuButton أحد عناصر واجهة المستخدم الهامة في Flutter التي تسمح للمستخدم بتحديد خيارات من القائمة المنبثقة عند النقر عليها. سنتعلم كيفية تعريف PopupMenuButton، واستخدامه لتحقيق مجموعة متنوعة من الوظائف المفيدة في التطبيقات، مثل إضافة وتعديل وحذف العناصر، وتغيير حالتها، وتنفيذ الإجراءات الإضافية. سيمكننا بناء على هذه المفاهيم لتطوير تطبيقات Flutter أكثر تفاعلية وقوية.
PopupMenuButton in flutter
في Flutter، يُستخدم عنصر واجهة المستخدم PopupMenuButton لإنشاء زر يفتح قائمة منبثقة تحتوي على عناصر قابلة للتحديد. يمكن استخدام هذا العنصر لتنفيذ أشياء مثل عرض خيارات القائمة أو تحديد قيمة من بين قائمة الخيارات.
عادةً، يتم استخدام PopupMenuButton في شريط الأدوات (AppBar) في التطبيقات لإنشاء زر يمكن للمستخدم فتحه لرؤية الخيارات المتاحة. عندما يقوم المستخدم بالنقر على الزر، يتم فتح القائمة المنبثقة ويمكنهم اختيار أحد الخيارات المعروضة.
يمكن تخصيص PopupMenuButton باستخدام العديد من الخيارات مثل تعيين القائمة المنبثقة وتحديد العنصر المُختار افتراضيًا وتعيين إجراء عند اختيار عنصر من القائمة.
مثال بسيط على كيفية استخدام PopupMenuButton في تطبيق Flutter:
PopupMenuButton<int>( itemBuilder: (BuildContext context) => <PopupMenuEntry<int>>[ const PopupMenuItem<int>( value: 1, child: Text('Option 1'), ), const PopupMenuItem<int>( value: 2, child: Text('Option 2'), ), const PopupMenuItem<int>( value: 3, child: Text('Option 3'), ), ], onSelected: (int value) { print(' selected: $value'); }, )
هنا، يتم إنشاء PopupMenuButton مع قائمة من ثلاثة خيارات ممثلة بعناصر القائمة المنبثقة (PopupMenuItem). عندما يُختار المستخدم أحد الخيارات، يتم تشغيل الدالة المعينة في onSelected مع القيمة المحددة كمعلم الوضعية.
في Flutter، يتيح لك PopupMenuButton إنشاء زر يفتح قائمة منبثقة تحتوي على عناصر قابلة للتحديد. إليك قائمة بالخصائص والمكونات الرئيسية والوظائف التي تأتي مع PopupMenuButton وكيفية استخدامها في الكود:
itemBuilder: يستخدم لتعريف العناصر التي سيتم عرضها في القائمة المنبثقة. يجب أن يكون نوعها List<PopupMenuEntry<T>>.
onSelected: يحدد الدالة التي سيتم استدعاؤها عند تحديد عنصر من القائمة. يمكن استخدامها لتنفيذ الإجراء المناسب بناءً على العنصر المحدد.
icon: يستخدم لتحديد الرمز المستخدم لعرض الزر.
offset: يحدد الإزاحة الأفقية والعمودية لموضع القائمة المنبثقة بالنسبة للزر.
enabled: يحدد ما إذا كان الزر يمكن النقر عليه أو لا.
tooltip: يستخدم لتحديد رسالة تعليماتية تظهر عند تحوي المؤشر إلى الزر.
child: يمكن استخدامه لتحديد عنصر واجهة المستخدم الذي يظهر كمحتوى الزر.
initialValue: يحدد القيمة المحددة افتراضيًا في القائمة المنبثقة.
للاستفادة منها في الكود، يمكنك استخدام PopupMenuButton كما يلي:
PopupMenuButton<int>( itemBuilder: (BuildContext context) => <PopupMenuEntry<int>>[ const PopupMenuItem<int>( value: 1, child: Text('Option 1'), ), const PopupMenuItem<int>( value: 2, child: Text('Option 2'), ), const PopupMenuItem<int>( value: 3, child: Text('Option 3'), ), ], onSelected: (int value) { // يتم استدعاء هذه الدالة عند تحديد عنصر من القائمة print(' selected: $value'); }, icon: Icon(Icons.more_vert), // تحديد الرمز المستخدم للزر tooltip: 'Options', // تحديد رسالة التعليماتية )
هذا مثال بسيط على كيفية استخدام PopupMenuButton في التطبيقات التي تستخدم Flutter. يمكنك تخصيصه بشكل أكبر باستخدام الخصائص الإضافية المذكورة أعلاه وفقًا لاحتياجات التطبيق الخاص بك.
شرح الكود سطرًا بسطر:
PopupMenuButton<int>(: يبدأ الكود بإنشاء عنصر PopupMenuButton بنوع القيمة المحددة int.
itemBuilder: (BuildContext context) => <PopupMenuEntry<int>>[: هذا السطر يحدد كيفية بناء عناصر القائمة المنبثقة. يتم تعريف العناصر في قائمة من النوع PopupMenuEntry<int>.
const PopupMenuItem<int>(value: 1, child: Text(‘Option 1’),),: يعرف هذا السطر عنصرًا من القائمة المنبثقة، حيث يحدد القيمة المرتبطة به ونص العنصر.
onSelected: (int value) { print(‘ selected: $value’); },: يحدد هذا السطر الدالة التي سيتم استدعاؤها عند تحديد عنصر من القائمة. في هذا المثال، يتم طباعة القيمة المحددة من القائمة.
icon: Icon(Icons.more_vert),: يحدد الرمز المستخدم لعرض الزر. في هذا المثال، يتم استخدام أيقونة رمزية لثلاث نقاط عمودية (more_vert) التي تشير إلى المزيد من الخيارات.
tooltip: ‘Options’,: يحدد رسالة تعليماتية تظهر عند تحويل المؤشر إلى الزر. في هذا المثال، سيظهر “Options” عند تحويل المؤشر إلى الزر.
): يغلق بناء PopupMenuButton.
هذا يوضح الكود سطرًا بسطر لكيفية استخدام PopupMenuButton في Flutter وتكوينه.
هاكم كيفية استخدام PopupMenuButton خطوة بخطوة في تطبيق Flutter:
الخطوة 1: استيراد الحزمة:
قبل استخدام PopupMenuButton، يجب عليك استيراد الحزمة الخاصة بها في ملف الكود الخاص بالشاشة التي تنوي استخدامها. يمكنك القيام بذلك باستخدام الكود التالي:
import 'package:flutter/material.dart';
الخطوة 2: استخدام PopupMenuButton:
يمكنك استخدام PopupMenuButton في مكان تفضيلي في واجهة المستخدم الخاصة بك، مثل داخل AppBar أو داخل Column أو Row، حسب متطلبات التصميم الخاصة بك.
AppBar( title: Text('My App'), actions: [ PopupMenuButton<int>( itemBuilder: (BuildContext context) => <PopupMenuEntry<int>>[ const PopupMenuItem<int>( value: 1, child: Text('Option 1'), ), const PopupMenuItem<int>( value: 2, child: Text('Option 2'), ), const PopupMenuItem<int>( value: 3, child: Text('Option 3'), ), ], onSelected: (int value) { // يتم استدعاء هذه الدالة عند تحديد عنصر من القائمة print(' selected: $value'); }, ), ], )
الخطوة 3: تخصيص الخيارات (اختياري):
يمكنك تخصيص PopupMenuButton باستخدام الخصائص الإضافية مثل icon لتحديد الأيقونة التي تعرضها الزر، tooltip لتوفير رسالة تعليماتية، و enabled لتمكين أو تعطيل الزر.
الخطوة 4: استجابة للاختيارات:
عندما يقوم المستخدم بتحديد عنصر من القائمة، سيتم تشغيل الدالة المعينة في onSelected ويتم تمرير القيمة المحددة كمعلم الوضعية.
هذه هي الخطوات الأساسية لاستخدام PopupMenuButton في تطبيق Flutter. تذكر أن يتم تعديل الرموز والنصوص وفقًا لاحتياجات تطبيقك الخاص.
تطبيق 1
الكود النهائي يظهر كيف يمكنك استخدام PopupMenuButton في تطبيق Flutter داخل AppBar. يمكنك نسخ ولصق الكود التالي في ملف main.dart الخاص بتطبيقك:
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('PopupMenuButton Example'), actions: [ PopupMenuButton<int>( itemBuilder: (BuildContext context) => <PopupMenuEntry<int>>[ const PopupMenuItem<int>( value: 1, child: Text('Option 1'), ), const PopupMenuItem<int>( value: 2, child: Text('Option 2'), ), const PopupMenuItem<int>( value: 3, child: Text('Option 3'), ), ], onSelected: (int value) { // يتم استدعاء هذه الدالة عند تحديد عنصر من القائمة print(' selected: $value'); }, ), ], ), body: Center( child: Text('Welcome to PopupMenuButton Example!'), ), ), ); } }
يقوم هذا التطبيق بعرض شريط عنوان يحتوي على زر PopupMenuButton في الجزء العلوي الأيمن. عند النقر على الزر، ستظهر قائمة منبثقة تحتوي على ثلاثة خيارات “Option 1″، “Option 2″، “Option 3”. وعند اختيار أحد الخيارات، ستطبع قيمة الخيار المحدد في وحدة تحكم الطباعة.
يمكنك تخصيص هذا الكود بحسب احتياجات التطبيق الخاص بك، مثل تغيير العناصر في القائمة أو تحديد إجراءات مختلفة عند اختيار عنصر من القائمة.
شجرة العناصر
ها هي شجرة العناصر في التطبيق:
MyApp └─ MaterialApp └─ Scaffold ├─ AppBar │ └─ PopupMenuButton └─ Center └─ Text
MyApp: يمثل واجهة التطبيق الرئيسية.
MaterialApp: يحتوي على الاعدادات العامة للتطبيق والمظهر الافتراضي.
Scaffold: يوفر هيكلًا لتطبيق الويب، ويحتوي عادةً على AppBar و Body.
AppBar: يظهر شريط العنوان في الأعلى ويحتوي على العنوان الرئيسي للتطبيق والأزرار.
PopupMenuButton: زر يفتح القائمة المنبثقة.
Center: يوسط عنصر واحد داخل Scaffold.
Text: يعرض نص “Welcome to PopupMenuButton Example!” في وسط الشاشة.
طبيق Flutter الذي سنقوم بإنشائه سيكون عبارة عن قائمة للمهام (To-Do List)، حيث سيتمكن المستخدم من إضافة المهام وتحديد مهمة كمكتملة وحذف المهام غير المطلوبة باستخدام PopupMenuButton.
الخطوات:
الخطوة 1: إعداد المشروع:
قم بإنشاء تطبيق Flutter جديد باستخدام أمر flutter create، أو استخدم بيئة تطوير مثل Android Studio أو Visual Studio Code.
الخطوة 2: تحرير main.dart:
قم بتحرير ملف main.dart لإنشاء تطبيق Flutter. يجب أن يكون ملف main.dart كالتالي:
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: TodoListScreen(), ); } } class TodoListScreen extends StatefulWidget { @override _TodoListScreenState createState() => _TodoListScreenState(); } class _TodoListScreenState extends State<TodoListScreen> { List<String> tasks = ['Task 1', 'Task 2', 'Task 3']; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('To-Do List'), actions: [ PopupMenuButton<String>( onSelected: (String result) { // تنفيذ الإجراء المناسب بناءً على الخيار المحدد setState(() { tasks.remove(result); }); }, itemBuilder: (BuildContext context) => tasks.map((String task) { return PopupMenuItem<String>( value: task, child: Text(task), ); }).toList(), ), ], ), body: ListView.builder( itemCount: tasks.length, itemBuilder: (context, index) { return ListTile( title: Text(tasks[index]), ); }, ), ); } }
الخطوة 3: تشغيل التطبيق:
قم بتشغيل التطبيق على محاكي الجهاز أو جهاز حقيقي للتحقق من الوظائف.
الشرح:
تم إنشاء تطبيق Flutter بسيط يستخدم Scaffold كهيكل للتطبيق.
تم إنشاء شريط عنوان (AppBar) يحتوي على عنوان “To-Do List”.
تم إضافة PopupMenuButton في الزاوية اليمنى العلوية من شريط العنوان. هذا الزر يظهر القائمة المنبثقة عند النقر عليه، والتي تحتوي على قائمة المهام.
تم استخدام ListView.builder لعرض قائمة المهام في الجزء الأسفل من الشاشة.
عندما يقوم المستخدم بتحديد مهمة من القائمة المنبثقة، يتم حذفها من قائمة المهام وتحديث الواجهة.
هذا تطبيق بسيط يستخدم PopupMenuButton لتحقيق وظيفة محددة، وهو حذف المهام من قائمة المهام. يمكنك توسيع التطبيق عن طريق إضافة المزيد من الوظائف مثل إضافة مهام جديدة أو تحديد المهام كمكتملة.
شجرة العناصر
بناءً على التطبيق الذي تم شرحه في الخطوة السابقة، إليك شجرة العناصر:
MyApp └─ MaterialApp └─ TodoListScreen └─ Scaffold ├─ AppBar │ └─ PopupMenuButton └─ ListView.builder └─ ListTile (Task 1) └─ ListTile (Task 2) └─ ListTile (Task 3)
MyApp: يمثل واجهة التطبيق الرئيسية.
MaterialApp: يحتوي على الاعدادات العامة للتطبيق والمظهر الافتراضي.
TodoListScreen: يمثل الشاشة الرئيسية لقائمة المهام.
Scaffold: يوفر هيكلًا لتطبيق الويب، ويحتوي على AppBar و Body.
AppBar: يظهر شريط العنوان في الأعلى ويحتوي على العنوان الرئيسي للتطبيق والأزرار.
PopupMenuButton: زر يفتح القائمة المنبثقة للمهام.
ListView.builder: يُظهر قائمة المهام باستخدام ListTile.
ListTile: يُظهر كل مهمة في القائمة.
لنقم ببناء تطبيق Flutter متقدم يستخدم PopupMenuButton بشكل متقدم. سنقوم بإنشاء تطبيق لإدارة قائمة الاتصالات، حيث يمكن للمستخدمين إضافة جهات اتصال جديدة وتعديلها وحذفها باستخدام PopupMenuButton.
الخطوات:
الخطوة 1: إعداد المشروع:
قم بإنشاء تطبيق Flutter جديد باستخدام أمر flutter create، أو استخدم بيئة تطوير مثل Android Studio أو Visual Studio Code.
الخطوة 2: تحرير main.dart:
قم بتحرير ملف main.dart لإنشاء تطبيق Flutter. يجب أن يكون ملف main.dart كالتالي:
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class Contact { final String name; final String phoneNumber; Contact(this.name, this.phoneNumber); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: ContactListScreen(), ); } } class ContactListScreen extends StatefulWidget { @override _ContactListScreenState createState() => _ContactListScreenState(); } class _ContactListScreenState extends State<ContactListScreen> { List<Contact> contacts = [ Contact('John Doe', '123-456-7890'), Contact('Jane Smith', '555-555-5555'), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Contacts'), actions: [ PopupMenuButton<Contact>( onSelected: (Contact contact) { // تنفيذ الإجراء المناسب بناءً على الخيار المحدد print('Selected contact: ${contact.name}'); }, itemBuilder: (BuildContext context) { return contacts.map((Contact contact) { return PopupMenuItem<Contact>( value: contact, child: Text(contact.name), ); }).toList(); }, ), ], ), body: ListView.builder( itemCount: contacts.length, itemBuilder: (context, index) { return ListTile( title: Text(contacts[index].name), subtitle: Text(contacts[index].phoneNumber), onTap: () { // تحرير جهة الاتصال عند النقر _editContact(context, contacts[index]); }, ); }, ), floatingActionButton: FloatingActionButton( onPressed: () { // إضافة جهة اتصال جديدة عند الضغط على الزر العائم _addContact(context); }, child: Icon(Icons.add), ), ); } void _addContact(BuildContext context) { // يمكنك إضافة التعليمات اللازمة لإضافة جهة اتصال جديدة هنا // في هذا المثال، سنطلب من المستخدم إدخال اسم الجهة ورقم الهاتف } void _editContact(BuildContext context, Contact contact) { // يمكنك إضافة التعليمات اللازمة لتعديل جهة الاتصال هنا // في هذا المثال، سنقوم بطباعة اسم الجهة الذي تم النقر عليه فقط print('Editing contact: ${contact.name}'); } }
الشرح:
تم إنشاء تطبيق Flutter بسيط يستخدم Scaffold كهيكل للتطبيق.
تم إضافة شريط عنوان (AppBar) يحتوي على عنوان “Contacts”.
تم إضافة PopupMenuButton في الزاوية اليمنى العلوية من شريط العنوان. هذا الزر يظهر القائمة المنبثقة التي تحتوي على قائمة الجهات الاتصال.
تم استخدام ListView.builder لعرض قائمة الجهات الاتصال في الجزء الأسفل من الشاشة.
يمكن للمستخدمين التفاعل مع الجهات الاتصال عن طريق النقر عليها، حيث يمكنهم تحرير كل جهة اتصال عند النقر عليها.
يمكن للمستخدمين أيضًا إضافة جهات اتصال جديدة باستخدام زر الإضافة العائم (FloatingActionButton).
ملاحظة:
في هذا المثال، لم يتم تنفيذ دالتي _addContact و _editContact بشكل كامل. يمكنك إضافة التعليمات اللازمة لإضافة جهات اتصال جديدة وتعديلها وحذفها بحسب احتياجات التطبيق الخاص بك.
الكود النهائي لتطبيق Flutter الذي يستخدم PopupMenuButton بدون أي خيارات فعّالة:
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class Contact { final String name; final String phoneNumber; Contact(this.name, this.phoneNumber); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: ContactListScreen(), ); } } class ContactListScreen extends StatefulWidget { @override _ContactListScreenState createState() => _ContactListScreenState(); } class _ContactListScreenState extends State<ContactListScreen> { List<Contact> contacts = [ Contact('John Doe', '123-456-7890'), Contact('Jane Smith', '555-555-5555'), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Contacts'), actions: [ PopupMenuButton<Contact>( itemBuilder: (BuildContext context) { return []; }, ), ], ), body: ListView.builder( itemCount: contacts.length, itemBuilder: (context, index) { return ListTile( title: Text(contacts[index].name), subtitle: Text(contacts[index].phoneNumber), onTap: () { // لا يوجد أي عمل هنا لأن الخيارات معطلة }, ); }, ), floatingActionButton: FloatingActionButton( onPressed: () { // لا يوجد أي عمل هنا لأن الخيارات معطلة }, child: Icon(Icons.add), ), ); } }
هذا الكود يقوم بإنشاء تطبيق يعرض قائمة بجهات الاتصال، مع خيارات القائمة المنبثقة (PopupMenuButton) معطلة.
اضافة تحسينات للتطبيق
طبعًا، يمكننا إضافة بعض التحسينات للتطبيق لجعله أكثر استخدامًا ووظائف. إليك بعض الأفكار للتحسينات:
إضافة دالة إضافة جهة اتصال جديدة: يمكننا إضافة دالة تسمح للمستخدم بإضافة جهة اتصال جديدة.
تحسينات في واجهة المستخدم: يمكننا تحسين شكل وتصميم واجهة المستخدم، مثل إضافة صور لجهات الاتصال أو تخصيص الألوان والخطوط.
إضافة دالة تعديل جهة اتصال: يمكننا إضافة خيار للمستخدم لتعديل جهة اتصال موجودة بالفعل.
إضافة دالة حذف جهة الاتصال: يمكننا إضافة خيار للمستخدم لحذف جهة اتصال من القائمة.
تخزين البيانات بشكل محلي: يمكننا استخدام مكتبة مثل shared_preferences لتخزين قائمة الاتصالات بشكل محلي على الجهاز.
إضافة عناصر تفاعلية إضافية: يمكننا إضافة عناصر تفاعلية إضافية مثل خيارات الفرز والبحث.
سنقوم بإضافة دالة لإضافة جهة اتصال جديدة وخيارات لتعديل وحذف جهات الاتصال الموجودة.
إليك كيفية تنفيذ بعض التحسينات:
// في الدالة _ContactListScreenState: void _addContact(BuildContext context) { showDialog( context: context, builder: (BuildContext context) { String name = ''; String phoneNumber = ''; return AlertDialog( title: Text('Add Contact'), content: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( decoration: InputDecoration(labelText: 'Name'), onChanged: (value) => name = value, ), TextField( decoration: InputDecoration(labelText: 'Phone Number'), onChanged: (value) => phoneNumber = value, ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text('Cancel'), ), ElevatedButton( onPressed: () { if (name.isNotEmpty && phoneNumber.isNotEmpty) { setState(() { contacts.add(Contact(name, phoneNumber)); }); Navigator.pop(context); } }, child: Text('Add'), ), ], ); }, ); } void _editContact(BuildContext context, Contact contact) { showDialog( context: context, builder: (BuildContext context) { String name = contact.name; String phoneNumber = contact.phoneNumber; return AlertDialog( title: Text('Edit Contact'), content: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( decoration: InputDecoration(labelText: 'Name'), controller: TextEditingController(text: name), onChanged: (value) => name = value, ), TextField( decoration: InputDecoration(labelText: 'Phone Number'), controller: TextEditingController(text: phoneNumber), onChanged: (value) => phoneNumber = value, ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text('Cancel'), ), ElevatedButton( onPressed: () { if (name.isNotEmpty && phoneNumber.isNotEmpty) { setState(() { contact.name = name; contact.phoneNumber = phoneNumber; }); Navigator.pop(context); } }, child: Text('Save'), ), ], ); }, ); } void _deleteContact(Contact contact) { setState(() { contacts.remove(contact); }); }
هذه التحسينات تضيف ميزات جديدة للتطبيق، مما يجعله أكثر استخدامًا وفعالية. يمكنك توسيع التطبيق بمزيد من التحسينات وفقًا لاحتياجات التطبيق الخاص بك.
الكود النهائي بعد التحسين
ها هو الكود النهائي بعد إضافة التحسينات المقترحة:
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class Contact { String name; String phoneNumber; Contact(this.name, this.phoneNumber); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: ContactListScreen(), ); } } class ContactListScreen extends StatefulWidget { @override _ContactListScreenState createState() => _ContactListScreenState(); } class _ContactListScreenState extends State<ContactListScreen> { List<Contact> contacts = [ Contact('John Doe', '123-456-7890'), Contact('Jane Smith', '555-555-5555'), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Contacts'), actions: [ PopupMenuButton<Contact>( itemBuilder: (BuildContext context) { return []; }, ), ], ), body: ListView.builder( itemCount: contacts.length, itemBuilder: (context, index) { return ListTile( title: Text(contacts[index].name), subtitle: Text(contacts[index].phoneNumber), onTap: () { _editContact(context, contacts[index]); }, onLongPress: () { _deleteContact(contacts[index]); }, ); }, ), floatingActionButton: FloatingActionButton( onPressed: () { _addContact(context); }, child: Icon(Icons.add), ), ); } void _addContact(BuildContext context) { showDialog( context: context, builder: (BuildContext context) { String name = ''; String phoneNumber = ''; return AlertDialog( title: Text('Add Contact'), content: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( decoration: InputDecoration(labelText: 'Name'), onChanged: (value) => name = value, ), TextField( decoration: InputDecoration(labelText: 'Phone Number'), onChanged: (value) => phoneNumber = value, ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text('Cancel'), ), ElevatedButton( onPressed: () { if (name.isNotEmpty && phoneNumber.isNotEmpty) { setState(() { contacts.add(Contact(name, phoneNumber)); }); Navigator.pop(context); } }, child: Text('Add'), ), ], ); }, ); } void _editContact(BuildContext context, Contact contact) { showDialog( context: context, builder: (BuildContext context) { String name = contact.name; String phoneNumber = contact.phoneNumber; return AlertDialog( title: Text('Edit Contact'), content: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( decoration: InputDecoration(labelText: 'Name'), controller: TextEditingController(text: name), onChanged: (value) => name = value, ), TextField( decoration: InputDecoration(labelText: 'Phone Number'), controller: TextEditingController(text: phoneNumber), onChanged: (value) => phoneNumber = value, ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text('Cancel'), ), ElevatedButton( onPressed: () { if (name.isNotEmpty && phoneNumber.isNotEmpty) { setState(() { contact.name = name; contact.phoneNumber = phoneNumber; }); Navigator.pop(context); } }, child: Text('Save'), ), ], ); }, ); } void _deleteContact(Contact contact) { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text('Delete Contact'), content: Text('Are you sure you want to delete ${contact.name}?'), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text('Cancel'), ), ElevatedButton( onPressed: () { setState(() { contacts.remove(contact); }); Navigator.pop(context); }, child: Text('Delete'), ), ], ); }, ); } }
تمت إضافة تحسينات لإضافة وتعديل وحذف جهات الاتصال. يمكنك استخدام هذا الكود لبناء تطبيق لإدارة قائمة جهات الاتصال بشكل أكثر كفاءة.
شرح التطبيق
تطبيق إدارة قائمة جهات الاتصال:
عنوان التطبيق وتقديمه:
عنوان التطبيق: إدارة جهات الاتصال.
وصف التطبيق: تطبيق Flutter لإدارة وتنظيم قائمة جهات الاتصال بسهولة وفعالية.
التحضيرات الأولية:
استيراد مكتبات Flutter الضرورية.
تعريف نموذج لجهة الاتصال (Contact) بخصائص اسم ورقم الهاتف.
تطبيق واجهة المستخدم:
إنشاء واجهة التطبيق باستخدام MaterialApp وScaffold.
إنشاء شريط عنوان (AppBar) مع عنوان “Contacts”.
إضافة زر عائم (FloatingActionButton) لإضافة جهة اتصال جديدة.
استخدام ListView.builder لعرض قائمة جهات الاتصال.
تطبيق وظيفة إضافة جهة اتصال جديدة:
إنشاء دالة _addContact لإظهار نافذة حوار (Dialog) تسمح للمستخدم بإضافة جهة اتصال جديدة.
استخدام حقول نصية (TextField) لتلقي مدخلات المستخدم لاسم ورقم الهاتف.
إضافة أزرار لتأكيد إضافة الجهة الجديدة أو إلغاء العملية.
تطبيق وظيفة تعديل جهة الاتصال:
إنشاء دالة _editContact لإظهار نافذة حوار تسمح للمستخدم بتعديل جهة اتصال موجودة.
استخدام حقول نصية محدثة تعرض معلومات جهة الاتصال الحالية.
إضافة أزرار لتأكيد حفظ التعديلات أو إلغاء العملية.
تطبيق وظيفة حذف جهة الاتصال:
إنشاء دالة _deleteContact لعرض تأكيد حذف جهة الاتصال المحددة.
إضافة أزرار لتأكيد الحذف أو إلغاء العملية.
تحسينات وتوسيعات إضافية:
يمكن إضافة مزيد من التحسينات مثل تخزين البيانات محليًا، وإضافة صور لجهات الاتصال، وتحسين التصميم والواجهة.
يمكن أيضًا تحسين تجربة المستخدم وإضافة ميزات مثل البحث والتصفية.
هذا التوضيح يشرح كيفية بناء وتنظيم تطبيق إدارة جهات الاتصال باستخدام Flutter بشكل منظم ومنسق.
شجرة العناصر
هذه شجرة العناصر لتطبيق إدارة جهات الاتصال:
MyApp └─ MaterialApp └─ ContactListScreen └─ Scaffold ├─ AppBar │ └─ Text ("Contacts") └─ ListView.builder └─ ListTile (Contact 1) └─ ListTile (Contact 2) └─ ... └─ ListTile (Contact n)
MyApp: تمثل واجهة التطبيق الرئيسية.
MaterialApp: تحتوي على الاعدادات العامة للتطبيق والمظهر الافتراضي.
ContactListScreen: تمثل الشاشة الرئيسية لقائمة جهات الاتصال.
Scaffold: يوفر هيكلًا لتطبيق الويب، ويحتوي على AppBar و Body.
AppBar: يظهر شريط العنوان في الأعلى ويحتوي على عنوان “Contacts”.
ListView.builder: يُظهر قائمة جهات الاتصال باستخدام ListTile.
ListTile: يُظهر كل جهة اتصال في القائمة.
نستخدم PopupMenuButton في العديد من المهام، بما في ذلك:
إدارة البيانات: يمكن استخدام PopupMenuButton لتمكين المستخدمين من تنفيذ إجراءات مثل إضافة، تعديل، حذف أو عرض تفاصيل العناصر.
التحكم في الترتيب والفرز: يمكن أن تحتوي القائمة المنبثقة على خيارات للسماح للمستخدم بتغيير الترتيب أو الفرز للعناصر.
تحديد الإعدادات: يمكن استخدام PopupMenuButton لعرض خيارات الإعدادات التي يمكن للمستخدم تخصيصها وتغييرها.
توفير الإجراءات الإضافية: يمكن أن تحتوي القائمة المنبثقة على أي إجراءات إضافية أو خيارات تستند إلى سياق التطبيق، مثل مشاركة العناصر أو إرسالها إلى السلة.
التحكم في تدفق التطبيق: يمكن استخدام PopupMenuButton لتحديد الإجراءات التي يتخذها التطبيق عند تفاعل المستخدم، مثل فتح شاشات جديدة أو عرض تنبيهات.
التحكم في التصنيفات: يمكن استخدام PopupMenuButton لتوفير خيارات لتغيير تصنيفات العناصر أو فرزها حسب المعايير المختلفة.
باختصار، يمكن استخدام PopupMenuButton في أي سياق يتطلب التفاعل مع العناصر وتوفير خيارات متعددة للمستخدم.
سأقدم لك تطبيقًا شاملا يستخدم PopupMenuButton في إدارة قائمة مهام. في هذا التطبيق، سنقوم بتنظيم قائمة المهام وتوفير خيارات لإضافة مهمة جديدة، تعديل المهام الحالية، حذف المهام وتغيير حالتها (مثل اكتمالها).
الخطوات:
إعداد المشروع:
قم بإنشاء تطبيق Flutter جديد.
استيراد المكتبات اللازمة.
تعريف نموذج المهمة:
تعريف نموذج Task يحتوي على خصائص مثل العنوان والوصف وحالة الاكتمال.
بناء واجهة المستخدم:
استخدم ListView.builder لعرض قائمة المهام.
استخدم ListTile لعرض كل مهمة.
استخدم PopupMenuButton في كل ListTile لتوفير خيارات الإدارة.
تنفيذ الوظائف:
إضافة وظيفة لإضافة مهمة جديدة.
إضافة وظيفة لتعديل المهمة.
إضافة وظيفة لحذف المهمة.
إضافة وظيفة لتغيير حالة المهمة (اكتمالها).
تحسينات وتوسيعات:
يمكن إضافة تخزين المهام بشكل محلي باستخدام مكتبة مثل shared_preferences.
يمكن تحسين تجربة المستخدم بإضافة ميزات مثل البحث والتصنيف والتصفية.
يمكن تخصيص التصميم وتحسين الواجهة لجعل التطبيق أكثر جاذبية.
لتبسيط الأمور، سأقدم لك الكود المبسط الذي يحتوي على العناصر الأساسية لتطبيق إدارة قائمة المهام:
الكود:
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class Task { String title; String description; bool isCompleted; Task(this.title, this.description, {this.isCompleted = false}); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: TaskListScreen(), ); } } class TaskListScreen extends StatefulWidget { @override _TaskListScreenState createState() => _TaskListScreenState(); } class _TaskListScreenState extends State<TaskListScreen> { List<Task> tasks = [ Task('Task 1', 'Description 1'), Task('Task 2', 'Description 2', isCompleted: true), Task('Task 3', 'Description 3'), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Task Manager'), ), body: ListView.builder( itemCount: tasks.length, itemBuilder: (context, index) { return ListTile( title: Text(tasks[index].title), subtitle: Text(tasks[index].description), trailing: PopupMenuButton<Task>( itemBuilder: (context) => [ PopupMenuItem( child: Text('Edit'), value: tasks[index], ), PopupMenuItem( child: Text('Delete'), value: tasks[index], ), PopupMenuItem( child: Text(tasks[index].isCompleted ? 'Mark as Incomplete' : 'Mark as Complete'), value: tasks[index], ), ], onSelected: (task) { if (task == null) return; if (task.isCompleted) { setState(() { task.isCompleted = false; }); } else { // Implement edit and delete functionality here } }, ), ); }, ), floatingActionButton: FloatingActionButton( onPressed: () { // Implement add task functionality here }, child: Icon(Icons.add), ), ); } }
هذا التطبيق يعرض قائمة المهام ويتيح للمستخدمين تنفيذ الإجراءات مثل إضافة، تعديل، وحذف المهام، بالإضافة إلى تغيير حالتها (اكتمالها).
دعنا نقوم بإنشاء كويز على هذا الدرس. سأقدم لك سؤالًا يتعلق باستخدام PopupMenuButton في Flutter.
تعريف خيارات القائمة المنبثقة.
عرض النص الذي يمثل خيار القائمة.
تحديد العملية التي يتم تنفيذها عند اختيار الخيار.
تغيير الشكل الخارجي لخيارات القائمة المنبثقة.
الإجابة:
4. تغيير الشكل الخارجي لخيارات القائمة المنبثقة.
التفسير:
PopupMenuItem تستخدم في Flutter لتغيير الشكل الخارجي لخيارات القائمة المنبثقة. يمكن تخصيص نص ورمز لكل عنصر في القائمة المنبثقة باستخدام PopupMenuItem.
تعريف خيارات القائمة المنبثقة.
عرض النص الذي يمثل خيار القائمة.
تحديد العملية التي يتم تنفيذها عند اختيار الخيار.
تغيير الشكل الخارجي لخيارات القائمة المنبثقة.
الإجابة:
3. تحديد العملية التي يتم تنفيذها عند اختيار الخيار.
التفسير:
onSelected هي دالة تُحدد العملية التي يتم تنفيذها عند اختيار الخيار من القائمة المنبثقة. عندما يقوم المستخدم بتحديد أحد الخيارات في القائمة المنبثقة، يتم استدعاء هذه الدالة وتُمرر لها القيمة المُحددة كمعلمة.
تعريف خيارات القائمة المنبثقة.
عرض النص الذي يمثل خيار القائمة.
تحديد العملية التي يتم تنفيذها عند اختيار الخيار.
تغيير الشكل الخارجي لخيارات القائمة المنبثقة.
الإجابة:
تعريف خيارات القائمة المنبثقة.
التفسير:
itemBuilder هي دالة تُستخدم لتعريف وتخصيص خيارات القائمة المنبثقة. يتم استدعاء هذه الدالة عند فتح القائمة المنبثقة لتوفير قائمة الخيارات التي يمكن للمستخدم اختيارها.