
بعد تقرير Yura Luchaninov ، قررت أن أجرب Flutter بنفسي. لتمتد الدماغ ، وهكذا كان هناك شيء للاسترخاء مع الرجال في المطبخ. لقد سارت الأمور. بدأت أشاهد ، ثم أقرأ ، ثم أكتب. ويبدو أن كل شيء ينجح ، ويتم تشغيل التطبيقات ، وما يفسرونه أمر مفهوم ، كل شيء بسيط. ولكن ليس من دون "لكن" - لا يشرح الجميع. وبما أن النظام الأساسي ، YP ، النهج وحتى موضوع الموضوع جديد بالنسبة لي ، هذا النوع من الإزعاج ، لأنك "لا تبدأ" ، ولا تعرف حتى ما الذي تريد google: Dart / Flutter / Window / Screen / Route / Widget؟
بالطبع ، لم أكن أرغب في إعادة قراءة جميع وثائق Dart و Flutter وعناصر واجهة المستخدم الخاصة بها ، لأنني لم يكن لدي الكثير من الوقت ، وأردت فقط إلقاء نظرة فاحصة على Flutter. سيكون من الرائع إذا كان هناك دليل صغير يصف كل ما تحتاجه ، ولكن ليس أكثر ، لفهم وكتابة تطبيقات ليست معقدة للغاية على Flutter!
حول الدليل
معظم المقالات حول هذا الموضوع مكتوبة بشكل جيد وليست معقدة. المشكلة هي أن معظمهم يحتاجون إلى معرفة تعتبر من الأساسيات الأساسية ، ومع ذلك ، لم يتم ذكرها في مقالات أخرى تصف الأساسيات. في هذه السلسلة من المقالات ، أريد تصحيح هذا الوضع. لنبدأ من الصفر ، وبدون ترك أي مما سبق دون الانتباه ، سنطلق تطبيقًا أو عدة تطبيقات. في هذه العملية ، سوف نتعلم كيفية استخدام جميع المكونات الرئيسية ، وإنشاء واجهة فريدة ، والعمل مع الوحدات الأصلية ، وبالطبع ، نقوم بتجميع التطبيق لكلا النظامين الأساسيين .
سأكتب من منظور مطور الويب. من المرجح أن معظمكم على دراية بمكدس الويب ، والتماثل مع النظام الأساسي المألوف أفضل من القياس مع بناء المنازل أو أيا كان ، Animal ، Dog ، Foo ، Bar ...
سأحاول أن أوجز بإيجاز حتى لا يتأخر. وللأكثر فضولًا ، سأترك روابط مفيدة حول الموضوعات التي تمت مناقشتها.
Flutter هي منصة شابة ولكنها واعدة للغاية وقد جذبت بالفعل اهتمام الشركات الكبيرة التي أطلقت تطبيقاتها . هذه المنصة مثيرة للاهتمام لبساطتها التي يمكن مقارنتها بتطوير تطبيقات الويب ، وسرعة العمل على قدم المساواة مع التطبيقات الأصلية. يتم تحقيق أداء التطبيق وسرعة التطوير من خلال عدة تقنيات:
- على عكس العديد من منصات الهواتف المحمولة المعروفة اليوم ، لا يستخدم Flutter JavaScript بأي شكل من الأشكال. كلغة برمجة لـ Flutter ، اختاروا Dart ، التي يتم تجميعها في رمز ثنائي ، وبالتالي تحقيق سرعة العمليات المماثلة لـ Objective-C أو Swift أو Java أو Kotlin.
- لا يستخدم Flutter المكونات الأصلية ، مرة أخرى ، بأي شكل من الأشكال ، لذلك لا يتعين عليك كتابة أي طبقات للتواصل معها. بدلاً من ذلك ، مثل محركات الألعاب (وأنت تعلم أن الألعاب بها واجهة مستخدم ديناميكية للغاية) ، فإنها ترسم الواجهة بأكملها من تلقاء نفسها. الأزرار والنصوص وعناصر الوسائط والخلفية - كل هذا يتم رسمه داخل محرك الرسومات في Flutter نفسه. بعد ما سبق ، تجدر الإشارة إلى أن تطبيق "Hello World" على Flutter يشغل مساحة صغيرة جدًا: iOS ≈ 2.5Mb و Android ≈ 4Mb.
- يستخدم Flutter نهجًا إعلانيًا مستوحى من إطار الويب ReactJS المستند إلى الأدوات (في عالم الويب يسمى المكونات) لإنشاء واجهة المستخدم. من أجل زيادة أكبر في سرعة الواجهة ، يتم إعادة رسم الحاجيات حسب الحاجة - فقط عندما يتغير شيء فيها (تمامًا مثلما يفعل Virtual DOM في عالم الواجهة الأمامية للويب).
- بالإضافة إلى ذلك ، يحتوي الإطار على إعادة تحميل مضمنة ، وهو أمر مألوف للغاية للويب ، وما زال غير متاح على الأنظمة الأساسية الأصلية.
حول الفوائد العملية لهذه العوامل ، أوصي بشدة بقراءة مقال مطور Android الذي أعاد كتابة تطبيقه من Java إلى Dart وشارك انطباعاته. هنا أخرج فقط عدد الملفات / الأسطر من التعليمات البرمجية التي ذكرها قبل (مكتوب بلغة جافا) - 179/12176 ، وبعد (تمت إعادة كتابتها في Dart) - 31/1735. في الوثائق ، يمكنك العثور على وصف مفصل للميزات التقنية للمنصة . وهنا رابط آخر ، إذا كنت مهتمًا بمشاهدة أمثلة أخرى لتطبيقات العمل .
حول دارت
Dart هي لغة برمجة يجب أن نكتب بها تطبيقات Flutter. إنه بسيط للغاية ، وإذا كانت لديك خبرة في Java أو JavaScript ، فستتعلمها بسرعة.
حاولت كتابة مقال مراجعة عن Dart ، محاولًا وصف الحد الأدنى الضروري فقط لتعلم Flutter. ولكن هناك الكثير من الفروق الدقيقة في هذه اللغة لدرجة أنه على الرغم من المحاولات العديدة لكتابة مثل هذه المقالة ، ما زلت لا أستطيع أن أجعلها كاملة تمامًا وفي نفس الوقت قصيرة. من ناحية أخرى ، قام مؤلفو A Tour of the Dart Language بعمل ممتاز في هذا.
عن التدريب
هذا الموضوع ، مثل Dart ، موصوف جيدًا في الدليل الرسمي. يمكنني فقط نسخها هنا ، لكني لن أفعلها.
دون انتظار أي شيء ، نذهب إلى صفحة دليل التثبيت ، ونختار النظام الأساسي ونتبع الخطوات لتثبيت النظام الأساسي على نظامنا. في محررنا ، سنقوم بتوصيل المكونات الإضافية. في نفس الدليل هناك تعليمات لإعداد VS Code و IntelliJ . هناك أيضًا مكونات إضافية لـ Dart و Flutter لمحررك (عادة ما تحتاج إلى تثبيت اثنين). نطلق التطبيق ونتحقق من أدائه .
تلميح لمستخدمي OSX. أشعر بالأسف على المساحة التي تشغلها الإطارات المطلية للهاتف في محاكي iOS ، لذلك قمت بإيقاف تشغيلها وقمت بالتبديل إلى iPhone 8 (ليس "طويلاً"):
Hardware → Device → iOS # → iPhone 8
Window → Show Device Bezels
يمكنك العيش بدون أزرار ، لأن هناك مفاتيح اختصار: Shift + Cmd + H
- هذا هو المنزل ، Cmd + Right
- وهذا لقلب الهاتف ، ويمكن العثور على الباقي في قائمة Hardware
. ولكن أنصحك بتشغيل لوحة المفاتيح على الشاشة ، لأنه من المهم فهم ما إذا كان من الممكن العمل مع التطبيق عندما يتم حظر نصف الشاشة بانتظام بواسطة لوحة المفاتيح: Cmd + K
(يعمل عندما يكون التركيز على بعض مجال الإدخال).
iPhone 8 و iPhone X مع إطارات

iPhone 8 و iPhone X بلا حدود

حول الهيكل
سنذهب إلى المجلد مع التطبيق الذي تم إنشاؤه ونرى ما لدينا هناك. ليس مع كل شيء ، ولكن مع الحق:
lib/
- وفقًا لمبادئ الحانة (مدير حزم Dart) ، تقع جميع التعليمات البرمجية في هذا المجلد الفرعي ؛pubspec.yml
- تتم كتابة تبعيات التطبيق هنا وتحتاج إلى تثبيتها لتشغيلها ، تمامًا مثل package.json
، ولكن هناك فارق بسيط ، تحتاج إلى تثبيتها ليس من خلال أداة Dart القياسية المذكورة أعلاه ، ولكن من خلال أمر Flutter: flutter pub get <package_name>
؛test/
- هل تعرف ما هو هناك؟ يمكنك تشغيلها عن طريق استدعاء flutter test
.- مجلدات
ios/
& android/
- مع إعدادات لكل نظام أساسي ، فإنه يشير إلى الحقوق اللازمة لتشغيل التطبيق (الوصول إلى الموقع والبلوتوث) والرموز وكل شيء خاص بالنظام الأساسي.
اكتشفنا الهيكل ، انتقل إلى lib/
المجلد حيث main.dart
ملف main.dart
لنا. هذا ، كما يمكنك تخمينه ، هو نفس الملف الذي يجب أن ندير فيه تطبيقنا. ويبدأ كما في C (وحتى أطنان أخرى) عن طريق استدعاء الوظيفة main()
.
حول الحاجيات (Hello World هنا)
في Flutter ، كل شيء مبني على عناصر واجهة المستخدم : هناك طرق عرض وأنماط ذات سمات وحالة في عناصر واجهة المستخدم. هناك نوعان رئيسيان من الأدوات: مع أو بدون حالة ، ولكن ليس حول ذلك حتى الآن. دعونا نجعلها سهلة.
قم بإزالة كل شيء من main.dart . قم بلصق التعليمة البرمجية التالية قراءة التعليقات بعناية.
import 'package:flutter/widgets.dart';
runApp(…)
وسيطة واحدة - القطعة التي ستكون الجذر للمشروع بأكمله. بالمناسبة ، لا يمكن لـ Hot-reload التقاطه ، لذلك ستحتاج إلى إعادة تشغيل التطبيق.
Text(…)
- لا يستطيع Flutter عرض سلسلة على الشاشة فقط. لعرض النص ، يجب تحديد Text
. textDirection
. وهذه ليست محاذاة نصية مثل محاذاة text-align
، عند مقارنتها مع الويب ، فهي تناظرية direction
. جزء من واجهة برمجة التطبيقات لتدويل التطبيق. لن يعمل Text
حتى يعرف الاتجاه ، ولكن ليس عليك تحديده في كل مكان - بعد ذلك سنحلل كيفية ضبط اتجاه النص للتطبيق بأكمله.
هل أطلقت التطبيق بالفعل؟ "Hello World!" خارج! يبدو أنه ... نعم؟ ولكن من الواضح أن هناك خطأ ما.

يتم حظر النص بمعلومات النظام. لدينا كل مساحة الشاشة تحت تصرفنا ، وأخرجنا الأداة في بدايتها ، حيث يتم عرض معلومات النظام ، من بين أمور أخرى. دعونا نحاول نقل نصنا إلى مكان ما.
import 'package:flutter/widgets.dart'; main() => runApp( Center(
Center(…)
هو عنصر واجهة مستخدم يسمح لك بوضع عنصر واجهة مستخدم آخر تم تمريره في الوسيطة child
في المركز أفقياً ورأسياً. غالبًا ما ستشاهد child
children
في تطبيقات Flutter ، نظرًا لأن جميع الأدوات تقريبًا تستخدم هذه الأسماء لنقل الأدوات التي يجب رسمها داخل القطعة التي تسمى
يتم استخدام تركيبات الأدوات في Flutter لتقديم واجهة المستخدم ، وتغيير المظهر ، وحتى نقل البيانات. على سبيل المثال ، يقوم عنصر واجهة تعامل Directionality(…)
بتعيين اتجاه النص لكل عناصر واجهة التعامل الفرعية:
import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Center( child: Text('Hello, World!'), ), ), );
دعونا نلقي نظرة على أداة أخرى مهمة للغاية وفي نفس الوقت نغير مظهر تطبيقنا:
import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Container(

Color(…)
- اللون. تشير الوثائق إلى طرق مختلفة لإعداده ، ولكن الشيء الرئيسي هو ببساطة تمرير الرقم إلى مُنشئ الصف. في المثال أعلاه ، نمرر المُنشئ رقمًا مكتوبًا في شكل سداسي عشري ، وهو مشابه جدًا لـ HEX ، فقط في البداية أضفنا حرفين آخرين يشيران إلى درجة شفافية اللون ، حيث يكون 0x00 شفافًا تمامًا و 0xFF غير شفاف على الإطلاق.
TextStyle(…)
هي أداة أكثر إثارة للاهتمام ، حيث يمكنك تعيين اللون والحجم والسمك وتباعد الخط وإضافة التسطير والمزيد.
تطبيق Flutter مكتوب ، تم! في الأحواض ، يمكنك قراءة كيفية تجميعها لنظامي التشغيل Android و iOS ، وهناك روابط في نفس المكان لإعلامك بكيفية إرسالها إلى المتجر المطلوب. لمن لا يكفي هذا ، ألقيت أدناه خطين إضافيين حول Flutter ، ربما أكثر ...
الحاجيات عديمي الجنسية الموالية
كيفية استخدام الأدوات - لقد اكتشفنا ، الآن دعونا نكتشف كيفية إنشائها. لقد سبق ذكره أعلاه أن هناك عناصر واجهة مستخدم لها حالة ولا توجد بها. حتى الآن ، استخدمنا فقط الحاجيات عديمة الجنسية. هذا لا يعني أنهم لا يملكونها على الإطلاق ، لأن الأدوات هي فئات فقط ، ويمكن تغيير خصائصها. بعد عرض الأداة ، لن يؤدي تغيير حالتها إلى تحديث هذه الأداة في واجهة المستخدم. على سبيل المثال ، إذا احتجنا إلى تغيير النص على الشاشة ، فسنحتاج إلى إنشاء أداة Text
أخرى وتحديد المحتوى الجديد الذي نريد عرضه. يمكن أن تسمى هذه الحاجيات ثابتة ، إذا كنت تعرف ما أعنيه. وهي بسيطة ، لذا فلنبدأ معهم.
لإنشاء أداة بدون حالة ، تحتاج إلى:
- ابتكر اسمًا جميلًا للفئة الجديدة ؛
- ترث فئة من
StatelessWidget
؛ - قم بتطبيق أسلوب
build()
يأخذ BuildContext
كوسيطة ويعيد نوعًا من Widget
.
import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Center( child: MyStatelessWidget() ), ), ); class MyStatelessWidget extends StatelessWidget {
عنصر واجهة استخدام مع وسيطة واحدة:
حول Stateless ، لا يوجد شيء آخر لإضافته ...
حول Hot Reload
يرجى ملاحظة أنه عند تغيير محتويات عنصر واجهة المستخدم ، سيتم إعادة رسم التطبيق تلقائيًا. بعد إزالة الأداة من الوظيفة main()
، بدأ Hot-reload في مساعدتنا.
من المهم أيضًا أن نفهم أنه نظرًا للوحدة التي تم إطلاقها للتبديل السريع ، يعمل التطبيق بترتيب حجم أبطأ.
حول GestureDetector

في القسم التالي ، سنتعامل مع StatefulWidget
(مع الأدوات التي تتغير عندما تتغير حالتها). لكي يكون هذا مثيرًا للاهتمام ، نحتاج إلى تغيير هذه الحالة بطريقة ما ، توافق؟ سنقوم بتغيير حالة القطعة ردا على اللمسات على الشاشة. للقيام بذلك ، سنستخدم GestureDetector(…)
- أداة لا تعرض أي شيء ، ولكنها تراقب اللمسات على شاشة الهاتف الذكي وتقارير حول استدعاء الوظائف المحولة إليها.
قم بإنشاء زر في وسط الشاشة ، عند النقر عليه ، سيتم عرض رسالة في وحدة التحكم:
import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Container( color: Color(0xFFFFFFFF), child: App(), ), ), ); class App extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: GestureDetector(
انقر على الزر الأزرق وشاهد الرسالة في وحدة التحكم. نضغط مرة أخرى ونرى مرة أخرى الرسالة في وحدة التحكم. مرة أخرى ... حسنًا ، توقف عن الالتصاق.
الحاجيات الدولة
StatefulWidget
- بسيطة ، وأبسط من StatelessWidget
. ولكن هناك فارق بسيط: فهي غير موجودة بمفردها ، لأن عملنا نحتاج إلى فئة أخرى تخزن حالة هذه القطعة. في الوقت نفسه ، يصبح الجزء المرئي (الحاجيات التي يتكون منها) حالته أيضًا.
للبدء ، انظر إلى فئة الأدوات:
أعلاه ، أنشأنا أداة "فارغة" نفذت طريقة createState()
بسيطة للغاية. يسمح هذا الفصل بين العرض التقديمي والحالة لـ Flutter بتحسين التطبيق بشكل كبير.
كائن الدولة غير معقد تمامًا. علاوة على ذلك ، إنه مطابق تقريبًا لـ StatelessWidget
المكتوبة من قبلنا أعلاه. اختلافه الرئيسي هو الطبقة الأصل.

لاحظ أن اسم الفئة يبدأ بشرطة سفلية سفلية. في Dart ، تحدد جميع الأسماء التي تبدأ بشرطة سفلية القيم الخاصة. وعادة ما يتم ترك حالة الحاجيات في Flutter خاصة ، على الرغم من أن هذا ليس ضروريًا.
يا له من تطبيق رائع قمنا به! هذه نتيجة رائعة. ولكن قبل الانتهاء من هذا الجزء من الدورة ، دعنا نلقي نظرة على بعض الحاجيات الأكثر إثارة للاهتمام. هذه المرة فقط سنكتب المزيد من التعليمات البرمجية ، فقط لجعلها أكثر إثارة للاهتمام. يجب أن يكون معظم التطبيق مألوفًا لك ، والباقي يجب أن تكون قد تعلمت بالفعل فهمه:
import 'package:flutter/widgets.dart'; main() => runApp(App()); class App extends StatelessWidget { @override Widget build(BuildContext context) { return Directionality( textDirection: TextDirection.ltr, child: Container( padding: EdgeInsets.symmetric( vertical: 60.0, horizontal: 20.0, ), color: Color(0xFFFFFFFF), child: Content(), ), ); } } class Content extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: [ Counter('Manchester United'), Counter('Juventus'), ], ); } } class Counter extends StatefulWidget { final String _name; Counter(this._name); @override State<Counter> createState() => _CounterState(); } class _CounterState extends State<Counter> { int count = 0; @override Widget build(BuildContext context) { return Container( margin: EdgeInsets.only(bottom: 10.0), padding: EdgeInsets.all(4.0), decoration: BoxDecoration( border: Border.all(color: Color(0xFFFD6A02)), borderRadius: BorderRadius.circular(4.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [

لدينا أداتان جديدتان: Column()
Row()
. حاول معرفة ما يفعلونه. في المقالة التالية ، سننظر فيها بمزيد من التفاصيل ، بالإضافة إلى إلقاء نظرة على أكثر من عنصر واجهة مستخدم يتيح لك إنشاء عناصر واجهة مستخدم أخرى معًا ، وإنشاء تطبيق لطيف باستخدام مكتبة Flutter تسمى المادة.
حول الواجبات المنزلية
إذا كنت تريد قراءة شيء آخر في وقت فراغك ، فإليك قائمة بالروابط المثيرة للاهتمام: