🧱 ما هي 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 | إخفاء لوحة المفاتيح |