🧱 ما هي SingleChildScrollView؟
SingleChildScrollView هي ويدجت في Flutter تسمح لك بتمرير (Scroll) عنصر واحد فقط عندما يتجاوز حجمه حجم الشاشة.
✅ هي الحل المثالي عندما:
- لديك محتوى كبير لا يتسع في الشاشة (مثل نموذج طويل).
- تريد أن تجعل الشاشة قابلة للتمرير عموديًا أو أفقيًا.
- تضع عنصرًا واحدًا قابلًا للتمرير — عادةً
Column.
🔁 الشكل العام:
SingleChildScrollView(
scrollDirection: Axis.vertical, // أو Axis.horizontal
child: Widget, // عنصر واحد فقط داخلها
)Dart📌 أهم الخصائص (Properties)
1. child ✅
العنصر الوحيد داخل
SingleChildScrollView— غالبًا يكونColumn,Row,Container, أو أي ويدجت كبيرة.
SingleChildScrollView(
child: Column(
children: [
Text('مرحبا'),
// ...
],
),
)Dart2. scrollDirection
الاتجاه الذي تريد فيه التمرير
Axis.vertical(افتراضي): تمرير عموديAxis.horizontal: تمرير أفقي
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(...),
)Dart3. reverse
إذا كنت تريد أن يبدأ التمرير من النهاية بدلاً من البداية.
SingleChildScrollView(
reverse: true,
child: Column(...),
)Dartمثال: مفيد في تطبيقات الدردشة بحيث تظهر الرسائل الأخيرة في الأسفل.
4. padding
لإضافة مسافة داخلية حول المحتوى.
SingleChildScrollView(
padding: EdgeInsets.all(16),
child: Column(...),
)Dart5. physics
تحدد طريقة التمرير (Scroll Behavior)
| النوع | التأثير |
|---|---|
AlwaysScrollableScrollPhysics() | يمكن التمرير دائمًا |
NeverScrollableScrollPhysics() | يمنع التمرير نهائيًا |
BouncingScrollPhysics() | يعطي تأثير “نطّ” مثل iOS |
ClampingScrollPhysics() | يشبه سلوك أندرويد التقليدي |
مثال:
SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Column(...),
)Dart6. keyboardDismissBehavior
تتحكم في إخفاء لوحة المفاتيح عند التمرير.
| القيمة | التأثير |
|---|---|
onDrag | تُخفى عند السحب |
manual | تحتاج تدخل يدوي |
مثال:
SingleChildScrollView(
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
child: Column(...),
)Dart🧠 ملاحظات مهمة جدًا:
✅ استخدمها مع Column عندما لا تكفي الشاشة لعرض المحتوى
SingleChildScrollView(
child: Column(
children: [
for (int i = 0; i < 30; i++) Text('عنصر $i'),
],
),
)Dart⚠️ لا تستخدم Expanded داخل Column إذا كانت داخل SingleChildScrollView
// ❌ هذا سيعطيك خطأ!
SingleChildScrollView(
child: Column(
children: [
Expanded(child: Container()), // غير مسموح هنا
],
),
)Dart🛠 الحل:
استخدم SizedBox بارتفاع معين بدلًا من Expanded.
🧪 تمرير أفقي
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: List.generate(
20,
(index) => Container(
width: 100,
height: 100,
color: Colors.primaries[index % Colors.primaries.length],
margin: EdgeInsets.all(8),
),
),
),
)Dart🧰 مثال واقعي لتطبيق يحتوي على Scroll:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('تسجيل الدخول')),
body: SingleChildScrollView(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text('أهلاً بك!', style: TextStyle(fontSize: 24)),
SizedBox(height: 20),
TextField(decoration: InputDecoration(labelText: 'البريد')),
SizedBox(height: 20),
TextField(decoration: InputDecoration(labelText: 'كلمة المرور')),
SizedBox(height: 30),
ElevatedButton(onPressed: () {}, child: Text('دخول')),
],
),
),
);
}Dart✅ خلاصة
| الخاصية | الاستخدام |
|---|---|
child | عنصر واحد فقط داخل الـ scroll |
scrollDirection | اتجاه التمرير |
reverse | التمرير من النهاية |
physics | نوع التمرير (نط، عادي، منع…) |
padding | مسافة داخلية |
keyboardDismissBehavior | إخفاء لوحة المفاتيح |