ما هو ListView العادي؟
ListView
العادي هو widget يعرض قائمة من العناصر القابلة للتمرير، حيث يتم تمرير جميع العناصر كـ children
في قائمة واحدة.
البنية الأساسية
ListView(
children: <Widget>[
<em>// قائمة العناصر هنا</em>
],
)
Dartجميع خصائص ListView العادي
1. children
الخاصية الأساسية لإضافة العناصر:
ListView(
children: <Widget>[
ListTile(title: Text('عنصر 1')),
ListTile(title: Text('عنصر 2')),
Card(child: Text('بطاقة')),
Container(height: 50, color: Colors.blue),
],
)
Dart2. scrollDirection
لتحديد اتجاه التمرير:
ListView(
scrollDirection: Axis.vertical, <em>// عمودي (افتراضي)</em>
<em>// أو</em>
scrollDirection: Axis.horizontal, <em>// أفقي</em>
children: [...],
)
Dart3. reverse
لعكس ترتيب العناصر:
ListView(
reverse: true, <em>// يبدأ من الأسفل إلى الأعلى</em>
children: [...],
)
Dart4. controller
للتحكم في التمرير:
final ScrollController _scrollController = ScrollController();
ListView(
controller: _scrollController,
children: [...],
)
Dart5. primary
لتحديد ما إذا كانت هذه القائمة هي الأساسية:
dart
ListView(
primary: true, <em>// افتراضي true إذا لم يكن هناك controller</em>
children: [...],
)
Dart6. physics
لتحديد سلوك التمرير:
ListView(
physics: BouncingScrollPhysics(), <em>// حركة مرنة</em>
<em>// أو</em>
physics: ClampingScrollPhysics(), <em>// حركة Android العادية</em>
<em>// أو</em>
physics: NeverScrollableScrollPhysics(), <em>// منع التمرير</em>
<em>// أو</em>
physics: AlwaysScrollableScrollPhysics(), <em>// التمرير دائماً</em>
children: [...],
)
Dart7. shrinkWrap
لتقليل حجم ListView:
ListView(
shrinkWrap: true, <em>// يأخذ المساحة المطلوبة فقط</em>
children: [...],
)
Dart8. padding
لإضافة مسافات حول القائمة:
ListView(
padding: EdgeInsets.all(16.0),
<em>// أو</em>
padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
children: [...],
)
Dart9. itemExtent
لتحديد ارتفاع ثابت لكل عنصر:
ListView(
itemExtent: 80.0, <em>// كل عنصر بارتفاع 80 بكسل</em>
children: [...],
)
Dart10. prototypeItem
لاستخدام عنصر نموذجي لتحديد الحجم:
ListView(
prototypeItem: ListTile(title: Text('نموذج')),
children: [...],
)
Dart11. addAutomaticKeepAlives
للحفاظ على حالة العناصر:
ListView(
addAutomaticKeepAlives: true, <em>// افتراضي true</em>
children: [...],
)
Dart12. addRepaintBoundaries
لتحسين الأداء:
ListView(
addRepaintBoundaries: true, <em>// افتراضي true</em>
children: [...],
)
Dart13. addSemanticIndexes
لإضافة فهارس دلالية:
ListView(
addSemanticIndexes: true, <em>// افتراضي true</em>
children: [...],
)
Dart14. cacheExtent
لتحديد مساحة التخزين المؤقت:
ListView(
cacheExtent: 250.0, <em>// افتراضي 250</em>
children: [...],
)
Dart15. semanticChildCount
لتحديد عدد العناصر للوصولية:
ListView(
semanticChildCount: children.length,
children: [...],
)
Dart16. dragStartBehavior
لتحديد سلوك بدء السحب:
ListView(
dragStartBehavior: DragStartBehavior.start, <em>// أو DragStartBehavior.down</em>
children: [...],
)
Dart17. keyboardDismissBehavior
لسلوك إخفاء لوحة المفاتيح:
ListView(
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
children: [...],
)
Dart18. restorationId
لحفظ واستعادة موضع التمرير:
ListView(
restorationId: 'list_view',
children: [...],
)
Dart19. clipBehavior
لتحديد سلوك القطع:
ListView(
clipBehavior: Clip.hardEdge, <em>// أو Clip.none, Clip.antiAlias</em>
children: [...],
)
Dartأمثلة عملية
مثال 1: ListView بسيط مع ListTile
class BasicListView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('ListView عادي')),
body: ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.home),
title: Text('الرئيسية'),
subtitle: Text('الصفحة الرئيسية'),
trailing: Icon(Icons.arrow_forward_ios),
),
ListTile(
leading: Icon(Icons.settings),
title: Text('الإعدادات'),
subtitle: Text('إعدادات التطبيق'),
trailing: Icon(Icons.arrow_forward_ios),
),
ListTile(
leading: Icon(Icons.person),
title: Text('الملف الشخصي'),
subtitle: Text('معلومات المستخدم'),
trailing: Icon(Icons.arrow_forward_ios),
),
],
),
);
}
}
Dartمثال 2: ListView أفقي مع بطاقات
class HorizontalListView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('ListView أفقي')),
body: Container(
height: 200,
child: ListView(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.all(10),
children: <Widget>[
Container(
width: 160,
child: Card(
child: Column(
children: [
Icon(Icons.star, size: 50, color: Colors.yellow),
Text('بطاقة 1'),
],
),
),
),
Container(
width: 160,
child: Card(
child: Column(
children: [
Icon(Icons.favorite, size: 50, color: Colors.red),
Text('بطاقة 2'),
],
),
),
),
Container(
width: 160,
child: Card(
child: Column(
children: [
Icon(Icons.thumb_up, size: 50, color: Colors.blue),
Text('بطاقة 3'),
],
),
),
),
],
),
),
);
}
}
Dartمثال 3: ListView مع ScrollController
class ControlledListView extends StatefulWidget {
@override
_ControlledListViewState createState() => _ControlledListViewState();
}
class _ControlledListViewState extends State<ControlledListView> {
final ScrollController _scrollController = ScrollController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('ListView مع التحكم')),
body: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () {
_scrollController.animateTo(
0,
duration: Duration(seconds: 1),
curve: Curves.easeInOut,
);
},
child: Text('للأعلى'),
),
ElevatedButton(
onPressed: () {
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
duration: Duration(seconds: 1),
curve: Curves.easeInOut,
);
},
child: Text('للأسفل'),
),
],
),
Expanded(
child: ListView(
controller: _scrollController,
children: List.generate(50, (index) {
return ListTile(
title: Text('عنصر رقم ${index + 1}'),
leading: CircleAvatar(child: Text('${index + 1}')),
);
}),
),
),
],
),
);
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
}
Dartمثال 4: ListView مع خصائص متقدمة
class AdvancedListView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('ListView متقدم')),
body: ListView(
padding: EdgeInsets.all(16.0),
physics: BouncingScrollPhysics(),
itemExtent: 100.0,
reverse: false,
children: <Widget>[
Container(
color: Colors.red[100],
child: Center(child: Text('عنصر 1', style: TextStyle(fontSize: 18))),
),
Container(
color: Colors.green[100],
child: Center(child: Text('عنصر 2', style: TextStyle(fontSize: 18))),
),
Container(
color: Colors.blue[100],
child: Center(child: Text('عنصر 3', style: TextStyle(fontSize: 18))),
),
Container(
color: Colors.yellow[100],
child: Center(child: Text('عنصر 4', style: TextStyle(fontSize: 18))),
),
Container(
color: Colors.purple[100],
child: Center(child: Text('عنصر 5', style: TextStyle(fontSize: 18))),
),
],
),
);
}
}
Dartالاستخدامات الشائعة
1. قوائم التنقل
ListView(
children: [
ListTile(title: Text('الرئيسية'), onTap: () {}),
ListTile(title: Text('المنتجات'), onTap: () {}),
ListTile(title: Text('من نحن'), onTap: () {}),
],
)
Dart2. عرض المعلومات
ListView(
children: [
Card(child: ListTile(title: Text('معلومة 1'))),
Card(child: ListTile(title: Text('معلومة 2'))),
Card(child: ListTile(title: Text('معلومة 3'))),
],
)
Dart3. النماذج الطويلة
ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: [
TextFormField(decoration: InputDecoration(labelText: 'الاسم')),
TextFormField(decoration: InputDecoration(labelText: 'الايميل')),
TextFormField(decoration: InputDecoration(labelText: 'الهاتف')),
],
)
Dartنصائح مهمة
- استخدم shrinkWrap: true عندما تضع ListView داخل Column
- استخدم physics: NeverScrollableScrollPhysics() إذا كنت لا تريد تمرير منفصل
- استخدم itemExtent إذا كانت جميع العناصر بنفس الحجم لتحسين الأداء
- تذكر dispose للـ ScrollController لتجنب تسرب الذاكرة
متى تستخدم ListView العادي؟
عندما لا تحتاج لبناء العناصر ديناميكياً
عندما يكون عدد العناصر قليل (أقل من 100)
عندما تريد عناصر مختلفة الأنواع
للقوائم الثابتة