1. مقدمة
تساعد المكونات المادية (MDC) المطورين على تنفيذ التصميم المتعدد الأبعاد. يضم مركز MDC، الذي أنشأه فريق من المهندسين ومصممي تجربة المستخدم في Google، عشرات من مكونات واجهة المستخدم الجميلة والعملية، وهو متاح لأجهزة Android وiOS والويب وFlutter.material.io/develop |
في درس تطبيقي حول الترميز MDC-101، استخدمت مكونَين من مكونات المواد لإنشاء صفحة تسجيل دخول، وهما الحقول النصية والأزرار التي تحتوي على تموجات الحبر. الآن دعنا نتوسع على هذا الأساس بإضافة التنقل والهيكل والبيانات.
ما الذي ستنشئه
في هذا الدرس التطبيقي حول الترميز، ستُنشئ شاشة رئيسية لتطبيق يُسمى Shrine، وهو تطبيق للتجارة الإلكترونية يبيع الملابس والسلع المنزلية. سيتضمّن المحتوى ما يلي:
- شريط التطبيق العلوي
- قائمة شبكية مليئة بالمنتجات
Android | iOS |
مكوّنات Material Flutter والأنظمة الفرعية الخاصة بها في هذا الدرس التطبيقي حول الترميز
- شريط التطبيق العلوي
- الشبكات
- البطاقات
ما هو تقييمك لمستوى خبرتك في تطوير Flutter؟
2. إعداد بيئة تطوير Flutter
لإكمال هذا التمرين، تحتاج إلى برنامجَين، وهما Flutter SDK ومحرِّر.
يمكنك تشغيل الدرس التطبيقي حول الترميز باستخدام أي من الأجهزة التالية:
- جهاز Android أو iOS فعلي متصل بجهاز الكمبيوتر وتم ضبطه على "وضع مطور البرامج".
- محاكي iOS (يتطلب تثبيت أدوات Xcode).
- محاكي Android (يتطلب الإعداد في "استوديو Android")
- متصفّح (يجب توفُّر متصفّح Chrome لتصحيح الأخطاء)
- كتطبيق سطح المكتب الذي يعمل بنظام التشغيل Windows أو Linux أو macOS. يجب إجراء عملية التطوير على النظام الأساسي الذي تنوي نشر التطبيق عليه. لذلك، إذا أردت تطوير تطبيق متوافق مع أجهزة الكمبيوتر المكتبي التي تعمل بنظام التشغيل Windows، عليك تطويره على نظام التشغيل Windows للوصول إلى سلسلة الإنشاء المناسبة. هناك متطلبات خاصة بنظام التشغيل يتم تناولها بالتفصيل على docs.flutter.dev/desktop.
3- تنزيل تطبيق Codelab Starter
هل ستتابع من MDC-101؟
إذا أكملت الدورة التدريبية MDC-101، من المفترض أن تكون رمزك مُعدّة لاستخدامها في هذا الدليل التعليمي. انتقِل إلى الخطوة: إضافة شريط تطبيق في أعلى الشاشة.
هل تريد البدء من نقطة الصفر؟
تنزيل تطبيق "الدرس التطبيقي حول الترميز" للمبتدئين
يمكن العثور على تطبيق التشغيل الأولي في دليل material-components-flutter-codelabs-102-starter_and_101-complete/mdc_100_series
.
...أو استنساخها من GitHub
لنسخ هذا الدليل التعليمي من GitHub، شغِّل الأوامر التالية:
git clone https://github.com/material-components/material-components-flutter-codelabs.git cd material-components-flutter-codelabs/mdc_100_series git checkout 102-starter_and_101-complete
فتح المشروع وتشغيل التطبيق
- افتح المشروع في المحرِّر الذي تختاره.
- اتّبِع تعليمات "تشغيل التطبيق" في البدء: تجربة التطبيق للمحرِّر الذي اخترته.
اكتمال عملية النقل بنجاح من المفترض أن تظهر لك صفحة تسجيل الدخول إلى Shrine من الدرس التطبيقي MDC-101 على جهازك.
Android | iOS |
بعد أن أصبحت شاشة تسجيل الدخول جيدة، لنضيف بعض المنتجات إلى التطبيق.
4. إضافة شريط تطبيق في أعلى الشاشة
في الوقت الحالي، إذا نقرت على الزر "التالي"، ستظهر لك الشاشة الرئيسية التي تعرض الرسالة "لقد نجحت". رائع. لا يحتاج المستخدم الآن إلى اتّخاذ أي إجراءات، أو أي معرفة بالمكان الذي يتصفّحه في التطبيق. وللمساعدة في ذلك، حان الوقت لإضافة تفاصيل عن ميزات التنقّل.
يوفر Material Design أنماط تنقل تضمن درجة عالية من قابلية الاستخدام. إنّ شريط التطبيق العلوي هو أحد العناصر الأكثر ظهورًا.
لتوفير إمكانية التنقل ومنح المستخدمين إمكانية الوصول السريع إلى إجراءات أخرى، يمكننا إضافة شريط تطبيق علوي.
إضافة تطبيق مصغّر لشريط التطبيقات
في home.dart
، أضِف AppBar إلى Scaffold وأزِل رمز const
المميّز:
return const Scaffold(
// TODO: Add app bar (102)
appBar: AppBar(
// TODO: Add buttons and title (102)
),
تؤدي إضافة AppBar إلى حقل appBar:
في Scaffold إلى الحصول على تصميم مثالي مجانًا، مع إبقاء AppBar أعلى الصفحة والنص أسفله.
إضافة تطبيق مصغّر للنص
في home.dart
، أضِف عنوانًا إلى AppBar:
// TODO: Add app bar (102)
appBar: AppBar(
// TODO: Add buttons and title (102)
title: const Text('SHRINE'),
// TODO: Add trailing buttons (102)
احفظ مشروعك.
Android | iOS |
تحتوي العديد من أشرطة التطبيقات على زر بجانب العنوان. لنضيف رمز قائمة في تطبيقنا.
إضافة رمز IconButton في المقدمة
أثناء استخدام home.dart
، يمكنك ضبط IconButton لحقل leading:
في AppBar. (ضعه قبل حقل title:
لمحاكاة الترتيب من الأعلى إلى الأسفل):
// TODO: Add buttons and title (102)
leading: IconButton(
icon: const Icon(
Icons.menu,
semanticLabel: 'menu',
),
onPressed: () {
print('Menu button');
},
),
احفظ مشروعك.
Android | iOS |
يظهر رمز القائمة (المعروف أيضًا باسم "الهامبرغر") في المكان الذي تتوقعه فيه.
يمكنك أيضًا إضافة أزرار إلى الجهة اللاحقة من العنوان. ويُطلق على هذه الإجراءات في Flutter اسم "الإجراءات".
إضافة إجراءات
هناك مساحة لزرَّي IconButton إضافيَّين.
أضِفها إلى مثيل AppBar بعد العنوان:
// TODO: Add trailing buttons (102)
actions: <Widget>[
IconButton(
icon: const Icon(
Icons.search,
semanticLabel: 'search',
),
onPressed: () {
print('Search button');
},
),
IconButton(
icon: const Icon(
Icons.tune,
semanticLabel: 'filter',
),
onPressed: () {
print('Filter button');
},
),
],
احفظ مشروعك. من المفترض أن تظهر شاشتك الرئيسية على النحو التالي:
Android | iOS |
يحتوي التطبيق الآن على زر بادئة وعنوان وإجراءين على الجانب الأيمن. يعرض شريط التطبيقات أيضًا الارتفاع باستخدام ظل خفيف يُظهر أنه على طبقة مختلفة عن المحتوى.
5- إضافة بطاقة في شبكة
الآن بعد أن أصبح تطبيقنا يتضمّن بعض البنية، لننظم المحتوى من خلال وضعه في بطاقات.
إضافة GridView
لنبدأ بإضافة بطاقة واحدة أسفل شريط التطبيقات العلوي. لا تحتوي أداة البطاقة وحدها على معلومات كافية لوضع نفسها في الأماكن التي يمكننا عرضها فيها، لذا نحتاج إلى تغليفها في أداة GridView.
استبدل المركز في نص السقالة بـ GridView:
// TODO: Add a grid view (102)
body: GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.all(16.0),
childAspectRatio: 8.0 / 9.0,
// TODO: Build a grid of cards (102)
children: <Widget>[Card()],
),
لنفكّ رمز هذا الرمز. تستدعي GridView count()
لأنّ عدد العناصر التي تعرِضها يمكن احتسابه وليس غير محدود. لكنها تحتاج إلى مزيد من المعلومات لتحديد تخطيطها.
وتحدّد السمة crossAxisCount:
عدد العناصر المضمّنة. نريد عمودين.
يقدّم الحقل padding:
مساحة على جميع الجوانب الأربعة من GridView. بطبيعة الحال، لا يمكنك رؤية المساحة المتروكة على الجوانب اللاحقة أو السفلية بسبب عدم وجود عناصر GridView بجانبها بعد.
يحدِّد الحقل childAspectRatio:
حجم العناصر استنادًا إلى نسبة العرض إلى الارتفاع (العرض على الارتفاع).
ينشئ GridView تلقائيًا مربّعات بنفس الحجم.
لدينا بطاقة واحدة ولكنها فارغة. لنضيف التطبيقات المصغّرة الفرعية إلى بطاقتنا.
تنسيق المحتوى
يجب أن تتضمّن البطاقات مناطق للصورة والعنوان والنص الثانوي.
عدِّل عناصر GridView:
// TODO: Build a grid of cards (102)
children: <Widget>[
Card(
clipBehavior: Clip.antiAlias,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: 18.0 / 11.0,
child: Image.asset('assets/diamond.png'),
),
Padding(
padding: const EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Title'),
const SizedBox(height: 8.0),
Text('Secondary Text'),
],
),
),
],
),
)
],
تضيف هذه التعليمة البرمجية أداة عمود تُستخدم لتخطيط الأدوات الفرعية عموديًا.
يحدِّد الرمز crossAxisAlignment: field
الرمز CrossAxisAlignment.start
، ما يعني "محاذاة النص مع الحافة الأمامية".
تحدِّد أداة AspectRatio شكل الصورة بغض النظر عن نوع الصورة المقدَّمة.
تؤدي المساحة المتروكة إلى إدخال النص من الجانب قليلاً.
يتم تجميع تطبيقَي النص المصغّرَين عموديًا مع ترك 8 نقاط من المساحة الفارغة بينهما (SizedBox). نُنشئ عمودًا آخر لوضعها داخل "المسافة البادئة".
احفظ مشروعك.
Android | iOS |
في هذه المعاينة، يمكنك رؤية أنّ البطاقة مضمّنة من الحافة، مع زوايا مستديرة وظلال (توضّح ارتفاع البطاقة). يُطلق على الشكل بأكمله اسم "الحاوية" في Material. (يجب عدم الخلط بين هذه الفئة وفئة التطبيق المصغّر الفعلية التي تُسمى Container).
تظهر البطاقات عادةً في مجموعة مع بطاقات أخرى. لنرتِّبها كمجموعة في شبكة.
6- إنشاء مجموعة بطاقات
عند وجود بطاقات متعددة في شاشة، يتم تجميعها معًا في مجموعة واحدة أو أكثر. تكون البطاقات في المجموعة على مستوى مستوٍ، ما يعني أنّ البطاقات تشترك في الارتفاع نفسه (ما لم يتم رفع البطاقات أو سحبها، ولكن لن نفعل ذلك هنا).
مضاعفة البطاقة في مجموعة
يتم الآن إنشاء البطاقة بشكل مضمّن في الحقل children:
في GridView. هذا رمز مُدمَج كثير قد يكون من الصعب قراءته. دعونا نستخرجها إلى دالة يمكنها إنشاء أكبر عدد ممكن من البطاقات الفارغة، مع عرض قائمة بالبطاقات.
أنشئ دالة خاصة جديدة فوق دالة build()
(تذكَّر أنّ الدوال التي تبدأ بشرطة سفلية هي واجهات برمجة تطبيقات خاصة):
// TODO: Make a collection of cards (102)
List<Card> _buildGridCards(int count) {
List<Card> cards = List.generate(
count,
(int index) {
return Card(
clipBehavior: Clip.antiAlias,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: 18.0 / 11.0,
child: Image.asset('assets/diamond.png'),
),
Padding(
padding: const EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const <Widget>[
Text('Title'),
SizedBox(height: 8.0),
Text('Secondary Text'),
],
),
),
],
),
);
},
);
return cards;
}
أضِف البطاقات التي تمّ إنشاؤها إلى الحقل children
في GridView. تذكَّر استبدال كل المحتوى المضمّن في GridView بهذا الرمز الجديد:
// TODO: Add a grid view (102)
body: GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.all(16.0),
childAspectRatio: 8.0 / 9.0,
children: _buildGridCards(10) // Replace
),
احفظ مشروعك.
Android | iOS |
البطاقات متوفّرة، لكنها لا تعرض أي شيء حتى الآن. حان الوقت الآن لإضافة بيانات المنتجات.
إضافة بيانات المنتج
يحتوي التطبيق على بعض المنتجات التي تحتوي على صور وأسماء وأسعار. لنضيف ذلك إلى التطبيقات المصغّرة المتوفّرة في البطاقة
بعد ذلك، في home.dart
، استورِد حزمة جديدة وبعض الملفات التي وفّرناها لنموذج بيانات:
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'model/product.dart';
import 'model/products_repository.dart';
أخيرًا، غيِّر _buildGridCards()
لعرض معلومات المنتج، واستخدِم هذه البيانات في البطاقات:
// TODO: Make a collection of cards (102)
// Replace this entire method
List<Card> _buildGridCards(BuildContext context) {
List<Product> products = ProductsRepository.loadProducts(Category.all);
if (products.isEmpty) {
return const <Card>[];
}
final ThemeData theme = Theme.of(context);
final NumberFormat formatter = NumberFormat.simpleCurrency(
locale: Localizations.localeOf(context).toString());
return products.map((product) {
return Card(
clipBehavior: Clip.antiAlias,
// TODO: Adjust card heights (103)
child: Column(
// TODO: Center items on the card (103)
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: 18 / 11,
child: Image.asset(
product.assetName,
package: product.assetPackage,
// TODO: Adjust the box size (102)
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 8.0),
child: Column(
// TODO: Align labels to the bottom and center (103)
crossAxisAlignment: CrossAxisAlignment.start,
// TODO: Change innermost Column (103)
children: <Widget>[
// TODO: Handle overflowing labels (103)
Text(
product.name,
style: theme.textTheme.titleLarge,
maxLines: 1,
),
const SizedBox(height: 8.0),
Text(
formatter.format(product.price),
style: theme.textTheme.titleSmall,
),
],
),
),
),
],
),
);
}).toList();
}
ملاحظة: لن يتم التجميع وتشغيله في الوقت الحالي. لدينا تغيير آخر.
غيِّر أيضًا الدالة build()
لتمرير BuildContext إلى _buildGridCards()
قبل محاولة الترجمة:
// TODO: Add a grid view (102)
body: GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.all(16.0),
childAspectRatio: 8.0 / 9.0,
children: _buildGridCards(context) // Changed code
),
أعِد تشغيل التطبيق فورًا.
Android | iOS |
قد تلاحظ أنّنا لا نضيف أيّ مسافة عمودية بين البطاقات. ويعود السبب في ذلك إلى أنّها تحتوي تلقائيًا على 4 نقاط هامش في أعلى وأسفل الصفحة.
احفظ مشروعك.
تظهر بيانات المنتج، ولكن هناك مساحة إضافية حول الصور. يتم رسم الصور باستخدام BoxFit .scaleDown
تلقائيًا (في هذه الحالة). لنغيّر ذلك إلى .fitWidth
ليتم التكبير قليلاً وإزالة المسافة البيضاء الإضافية.
أضِف حقل fit:
إلى الصورة مع القيمة BoxFit.fitWidth
:
// TODO: Adjust the box size (102)
fit: BoxFit.fitWidth,
Android | iOS |
وتظهر منتجاتنا الآن في التطبيق بشكل مثالي.
7- تهانينا!
يحتوي تطبيقنا على تدفق أساسي ينقل المستخدم من شاشة تسجيل الدخول إلى الشاشة الرئيسية، حيث يمكن عرض المنتجات. في بضعة أسطر فقط من التعليمات البرمجية، أضفنا شريط التطبيق العلوي (بعنوان وثلاثة أزرار) وبطاقات (لتقديم محتوى تطبيقنا). أصبحت شاشتنا الرئيسية الآن بسيطة وعملية، وتتميز بهيكل أساسي ومحتوى قابلاً للتنفيذ.
الخطوات التالية
باستخدام شريط التطبيق العلوي والبطاقة وحقل النص والزر، استخدمنا الآن أربعة مكوّنات أساسية من مكتبة Material Flutter. يمكنك التعرّف على المزيد من المعلومات من خلال الانتقال إلى كتالوج التطبيقات المصغّرة لمكونات Material.
على الرغم من أنّ تطبيقنا يعمل بشكل كامل، لا يعبّر بعد عن أي علامة تجارية أو وجهة نظر معيّنة. في MDC-103: مظهر التصميم المتعدد الأبعاد حسب اللون والشكل والارتفاع والنوع، سنخصِّص نمط هذه المكوّنات للتعبير عن علامة تجارية عصرية ونابضة بالحياة.