Flutter Widgets — اللبنات الأساسية لواجهة المستخدم في إطار Google Flutter، الذي صدر في النسخة المستقرة 1.0 في ديسمبر 2018. في Flutter، كل شيء هو قطعة: من الشاشات والأزرار إلى الهوامش والمحاذاة. تشكل القطع شجرة (widget tree) يقوم Flutter بعرضها على محرك Skia/Impeller الخاص به، متجاوزًا المكونات الأصلية للمنصة. وفقًا لـ Google I/O (2025)، يُستخدم Flutter في أكثر من 500,000 تطبيق على Google Play و App Store. تقسم بنية Flutter القطع إلى StatelessWidget (غير قابلة للتغيير) و StatefulWidget (بحالة قابلة للتغيير عبر كائن State).
النقاط الرئيسية
Flutter Widgets — جميع عناصر واجهة المستخدم في إطار Flutter، المنفذة كفئات Dart غير قابلة للتغيير. القطعة هي تكوين عنصر واجهة المستخدم: حجمها ولونها وموضعها ومعالجات الأحداث. على عكس Android (XML + View) أو iOS (Storyboard + UIView)، لا يستخدم Flutter المكونات الأصلية — كل شيء يُرسم بواسطة محرك Skia (Android/iOS/Linux) أو Impeller (iOS/macOS) على Canvas. يضمن هذا مظهرًا متسقًا على جميع المنصات دون اختلافات منصة. يأتي Flutter مع مجموعتين من القطع: Material Widgets (تصميم Google Material Design 3 لنظام Android والويب) و Cupertino Widgets (تصميم Apple HIG لنظامي iOS/macOS). يمكن للمطور دمج المجموعتين في تطبيق واحد. كل قطعة لها طريقة build() تعيد قطعة فرعية أو تركيبًا منها — هكذا تُبنى شجرة القطع.
يعمل Flutter بثلاث أشجار: Widget Tree (التكوين، ينشئه المطور)، Element Tree (ربط القطعة بموقعها في الشجرة، يديره الإطار) و Render Tree (الكائنات التي تحسب التخطيط وتنفذ الرسم). تنشئ القطعة Element، الذي ينشئ RenderObject. يُعاد استخدام Element عندما يتغير التكوين (rebuild) — هذه آلية تحسين Flutter: إذا تطابق نوع القطعة والمفتاح، لا يُعاد إنشاء Element بل يُحدث بالتكوين الجديد. فهم الأشجار الثلاثة هو مفتاح تحسين أداء تطبيقات Flutter.
StatelessWidget — قطعة لا تخزن حالة داخلية. تستقبل معاملات عبر المنشئ وتعرضها دون إمكانية التغيير بعد البناء. StatelessWidget مثالي للعناصر الثابتة: الرؤوس والأيقونات والصور الرمزية والقوائم ذات البيانات الثابتة. تُستدعى طريقة build() مرة واحدة عند الإنشاء وعندما يتغير القطعة الأم. نظرًا لأن StatelessWidget ليس له حالة، فإنه لا يتطلب كائن State منفصل — تُعرف build() مباشرة في فئة القطعة.
import 'package:flutter/material.dart';
class ProfileHeader extends StatelessWidget {
final String name;
final String avatarUrl;
const ProfileHeader({super.key, required this.name, required this.avatarUrl});
@override
Widget build(BuildContext context) {
return Row(
children: [
CircleAvatar(
radius: 24,
backgroundImage: NetworkImage(avatarUrl),
),
const SizedBox(width: 12),
Text(
name,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
);
}
}ProfileHeader — StatelessWidget يستقبل name و avatarUrl عبر المنشئ. يعرض CircleAvatar الصورة الرمزية ويعرض Text الاسم. لا يمكن للقطعة تغيير هذه القيم بعد الإنشاء. استخدام منشئ const (const ProfileHeader) يسمح لـ Flutter بإعادة استخدام مثيل القطعة أثناء إعادة بناء القطعة الأم — تحسين دقيق موصى به لجميع StatelessWidget.
StatefulWidget — قطعة بحالة قابلة للتغيير مخزنة في كائن State منفصل. StatefulWidget نفسه غير قابل للتغيير، مثل StatelessWidget. الجزء القابل للتغيير يُفوض إلى State: State هو كائن يُنشأ مرة واحدة ويبقى عبر عمليات إعادة بناء متعددة للقطعة. عندما تتغير الحالة (setState())، يستدعي Flutter build() على State، محدثًا واجهة المستخدم. يُستخدم StatefulWidget للعناصر التفاعلية: العدادات وحقول النص ومربعات الاختيار والرسوم المتحركة والمؤقتات.
import 'package:flutter/material.dart';
class LikeButton extends StatefulWidget {
const LikeButton({super.key});
@override
State<LikeButton> createState() => _LikeButtonState();
}
class _LikeButtonState extends State<LikeButton> {
bool liked = false;
int count = 42;
void _toggleLike() {
setState(() {
liked = !liked;
count += liked ? 1 : -1;
});
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _toggleLike,
child: Text(liked ? '♥ $count' : '♡ $count'),
);
}
}LikeButton — StatefulWidget مع فئة State _LikeButtonState. الحقلان liked و count هما حالة مخزنة في State ولا يُعاد تعيينهما عند إعادة البناء. setState() يخطر Flutter بأن واجهة المستخدم تحتاج إلى إعادة بناء. لا يعيد Flutter إنشاء State عند كل إعادة بناء للأم — فقط عندما يتغير التكوين (المفتاح أو نوع القطعة). في IT Sectr، نستخدم StatelessWidget للعرض و StatefulWidget للمكونات التفاعلية، متبعين مبدأ تقليل StatefulWidget إلى حدود التغيير.
Widget Tree — هيكل هرمي للقطع يصف واجهة مستخدم التطبيق. يحول Flutter Widget Tree إلى Element Tree: كل قطعة تنشئ Element، الذي يتتبع موقعها في الشجرة واتصالها بـ RenderObject. ينفذ Render Tree التخطيط (تحديد الأحجام والمواضع) والرسم (العرض). Element هو طبقة تحسين رئيسية: إذا لم يتغير نوع القطعة والمفتاح أثناء إعادة البناء، يُعاد استخدام Element، محدثًا التكوين دون إعادة إنشاء RenderObject. يضمن هذا أداء Flutter بمعدلات إطارات عالية (60/120 FPS).
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('قطع Flutter')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.flutter_dash, size: 80),
const SizedBox(height: 16),
const Text(
'مرحبًا، Flutter!',
style: TextStyle(fontSize: 24),
),
],
),
),
);
}
}شجرة قطع HomeScreen: Scaffold → AppBar + Center → Column → [Icon, SizedBox, Text]. Scaffold هو القطعة الجذرية لتخطيط Material Design. Center توسيط Column التابعة. Column ترتب الأطفال رأسيًا بمحاذاة في الوسط (mainAxisAlignment.center). يحسب Flutter التخطيط من الأعلى للأسفل (تُمرر القيود من الوالد) والأحجام من الأسفل للأعلى (sizedByParent أو sizing from children).
BuildContext — واصف لموقع القطعة في Element Tree. كل طريقة build() تستقبل BuildContext، يمكن للقطعة من خلاله الوصول إلى: MediaQuery (حجم الشاشة والاتجاه وكثافة البكسل والمنطقة الآمنة)، Theme (MaterialThemeData أو CupertinoThemeData)، Navigator (مكدس التنقل)، ScaffoldMessenger (SnackBar)، InheritedWidget (تمرير البيانات لأسفل الشجرة). لا يجب حفظ BuildContext بعد انتهاء build() أو استخدامه خارج سياق متزامن — يؤدي هذا إلى أخطاء مثل “Scaffold.of() called with a context that does not contain a Scaffold”. بدلاً من حفظ context، استخدم قطعة Builder أو نمط InheritedWidget للوصول إلى البيانات.
Key — معامل اختياري لمنشئ كل قطعة (super.key). يساعد Key Flutter في تعريف القطعة عند تغيير ترتيب أو عدد العناصر في قائمة. بدون Key، يقارن Flutter القطع حسب النوع والموضع؛ عند إضافة عنصر في منتصف قائمة بدون Key، يُعيد Flutter استخدام Element للقطعة الخطأ، مسببًا أخطاء في الحالة (StatefulWidget) ومشاكل في الرسوم المتحركة. استخدم ValueKey (معرف فريد) للقوائم، ObjectKey (بناءً على كائن البيانات)، UniqueKey (مضمون الفريد في كل إعادة بناء — لإعادة الإنشاء القسري).
Flutter SDK (النسخة المستقرة 3.3+، Dart 3+) يتضمن أكثر من 200 قطعة مدمجة مقسمة إلى فئات: Layout (Row, Column, Stack, Container, Expanded, Flexible, Wrap, GridView, ListView, CustomScrollView)، Material Design (Scaffold, AppBar, Card, Drawer, BottomNavigationBar, FloatingActionButton, TabBar, Chip, DataTable)، Cupertino (CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton, CupertinoTabBar)، Painting & Effects (Opacity, DecoratedBox, ClipRect, Transform, BackdropFilter, ShaderMask)، Async (FutureBuilder, StreamBuilder) و Accessibility (Semantics, MergeSemantics, ExcludeSemantics). قطع التخطيط هي أساس أي واجهة Flutter: Row للتسلسلات الأفقية، Column للرأسية، Stack للعناصر المتداخلة، Container مع BoxDecoration للزخرفة.
| الفئة | القطع الرئيسية | الغرض |
|---|---|---|
| Layout | Row, Column, Stack, Container, Expanded, Flexible | تحديد موضع وأحجام العناصر الفرعية |
| Material | Scaffold, AppBar, Card, Drawer, FAB, TabBar | مكونات واجهة Material Design 3 |
| Cupertino | CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton | مكونات بنمط iOS |
| Painting | Opacity, ClipRect, Transform, DecoratedBox, BackdropFilter | تأثيرات بصرية وقص |
| Async | FutureBuilder, StreamBuilder | تحميل بيانات غير متزامن مع حالات واجهة |
| Accessibility | Semantics, MergeSemantics | ترميز دلالي لقارئات الشاشة |
الأسئلة الشائعة
StatelessWidget ليس له حالة داخلية — جميع البيانات تُمرر عبر المنشئ ولا تتغير. يخزن StatefulWidget الحالة القابلة للتغيير في كائن State منفصل يبقى بعد إعادة البناء. تغيير الحالة يستدعي setState()، ويقوم Flutter بإعادة بناء واجهة المستخدم. استخدم StatelessWidget للعناصر غير القابلة للتغيير؛ واستخدم StatefulWidget للعناصر التفاعلية.
BuildContext هو واصف لموقع القطعة في Element Tree، يُمرر إلى طريقة build(). من خلال context، تحصل القطعة على الوصول إلى MediaQuery و Theme و Navigator و ScaffoldMessenger و InheritedWidget. لا يجب حفظ BuildContext بعد انتهاء build(). للوصول إلى البيانات، استخدم قطعة Builder أو InheritedWidget.
نعم، يستخدم Flutter Dart كلغة برمجة وحيدة. Dart هي لغة ثابتة الأنواع مع null safety و sound null safety و extension methods و pattern matching. للبدء، يكفي معرفة أساسيات Dart: الفئات والدوال و async/await والمجموعات. يُترجم Dart إلى كود أصلي (AOT) عبر Dart Native وإلى JavaScript (للويب) عبر Dart2JS.
لا، يدعم Flutter ست منصات: iOS و Android و Web و macOS و Windows و Linux. أكثر من 90٪ من الكود مشترك بين جميع المنصات. يتم تنفيذ تكييفات المنصة (الكاميرا ونظام الملفات) عبر الإضافات أو قنوات المنصة. لسطح المكتب، يستخدم Flutter غلاف نافذة Flutter Desktop؛ وللويب، يستخدم محرك CanvasKit (WebGL) أو عارض HTML.
يحقق Flutter 60/120 إطارًا في الثانية من خلال: محركه ثنائي الأبعاد (Skia/Impeller)، عدم وجود جسر أصلي (على عكس React Native)، ثلاثة أشجار (Widget → Element → Render) مع إعادة استخدام Element عندما لا يتغير النوع/المفتاح، وخوارزمية تخطيط باتجاه واحد (القيود للأسفل والأحجام للأعلى) و RepaintBoundary لعزل إعادة رسم مناطق فردية من الشاشة.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.