طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 251 · برمجة الأجهزة الذكية
الدرس 4 · الوحدة 2: تطوير واجهات المستخدم للأجهزة الذكية

اللمس والأزرار Pressable والقوائم FlatList

التفاعل باللمس وعرض القوائم بكفاءة. ⏱ نحو 40 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تستقبل اللمس بـ Pressable وتستجيب لحالة الضغط.
  • تعرف لماذا FlatList أفضل من map للقوائم الطويلة.
  • تعرض قائمةً بـ data و renderItem و keyExtractor.

١اللمس: Pressable

على الهاتف نتفاعل باللمس لا بالنقر. Pressable منطقةٌ تستقبل اللمس عبر onPress، وتعرف إن كان الإصبع فوقها عبر دالةٍ تتلقّى { pressed }:

import { useState } from 'react';import { View, Text, Pressable, StyleSheet } from 'react-native'; export default function App() {  const [likes, setLikes] = useState(0);  return (    <View style={{ padding: 24, alignItems: 'center' }}>      <Text style={styles.n}>❤️ {likes}</Text>      <Pressable        onPress={() => setLikes(likes + 1)}        style={({ pressed }) => [styles.btn, pressed && styles.pressed]}      >        <Text style={styles.t}>أعجبني</Text>      </Pressable>    </View>  );} const styles = StyleSheet.create({  n: { fontSize: 32, fontWeight: 'bold', marginBottom: 14 },  btn: { backgroundColor: '#E8820C', paddingVertical: 12, paddingHorizontal: 22, borderRadius: 12 },  pressed: { opacity: 0.6 },  t: { color: 'white', fontSize: 16 },});

لاحظ أن style يمكن أن تكون دالةً تستقبل حالة اللمس — فنغيّر المظهر أثناء الضغط.

٢القوائم الطويلة: لماذا FlatList؟

لعرض قائمةٍ قد تطول (مئات العناصر)، لا نرسمها كلها دفعةً واحدة — يستهلك ذاكرة الجهاز. FlatList يرسم المرئيّ فقط ويعيد تدوير العناصر عند التمرير (أساسٌ للأداء، وحدة 11):

map يدويًّاFlatList
يرسمكل العناصر دفعةالمرئيّ فقط
ذاكرةتكبر مع العددثابتة تقريبًا
مناسب لـقائمة قصيرةقائمة طويلة/غير محدودة

٣FlatList: data و renderItem و keyExtractor

ثلاث خصائص أساسية: data المصفوفة، وrenderItem دالةٌ ترسم كل عنصر، وkeyExtractor يعطي كلّ عنصرٍ مفتاحًا فريدًا:

import { View, Text, FlatList, StyleSheet } from 'react-native'; const PRODUCTS = [  { id: 'p1', name: 'قهوة', price: 18 },  { id: 'p2', name: 'شاي', price: 12 },  { id: 'p3', name: 'عصير', price: 15 },]; export default function App() {  return (    <FlatList      style={{ padding: 10 }}      data={PRODUCTS}      keyExtractor={(item) => item.id}      renderItem={({ item }) => (        <View style={styles.row}>          <Text style={styles.name}>{item.name}</Text>          <Text style={styles.price}>{item.price} ر.س</Text>        </View>      )}    />  );} const styles = StyleSheet.create({  row: { flexDirection: 'row', justifyContent: 'space-between', padding: 12, borderBottomWidth: 1, borderColor: '#eee' },  name: { fontSize: 16 },  price: { fontWeight: 'bold', color: '#E8820C' },});

renderItem يستقبل كائنًا فيه item (العنصر الحالي). keyExtractor يمنع تحذير المفاتيح ويسرّع التحديث.

توقّع وتحقّق

ما الذي يستقبل اللمس في React Native؟

لماذا نفضّل FlatList على map لقائمةٍ طويلة؟

أي خاصية ترسم كل عنصر في FlatList؟

دور keyExtractor:

الخلاصة

تحدٍّ برمجي: قائمة مهامّ

متوسط

اعرض قائمة مهامّ بـ FlatList، وزرًّا يزيد عدّاد المنجَز.

المطلوب:
  • عرّف مصفوفة مهامّ (3 عناصر على الأقل) لكلٍّ id وtitle.
  • اعرضها بـ FlatList مع keyExtractor، وكل عنوانٍ في <Text>.
  • أضف <Text testID="count"> يعرض عدد المهامّ.
👀 اعرض الناتج المطلوب (وجرّبه)
✓ التحقق الآلي من حلّك:
  • الكود يعمل بلا أخطاء في Console
  • العدّاد يعرض 3
  • تظهر ثلاث مهامّ على الأقل
  • استُخدم FlatList
  • استُخدم keyExtractor

💡 تلميح 1
FlatList يحتاج data و renderItem و keyExtractor.
💡 تلميح 2
العدّاد: TASKS.length.

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

import { View, Text, FlatList, StyleSheet } from 'react-native'; const TASKS = [  { id: 't1', title: 'مراجعة الدرس' },  { id: 't2', title: 'حلّ التحدي' },  { id: 't3', title: 'تسليم المشروع' },]; export default function App() {  return (    <View style={{ padding: 10 }}>      <Text testID="count" style={styles.count}>عدد المهامّ: {TASKS.length}</Text>      <FlatList        data={TASKS}        keyExtractor={(item) => item.id}        renderItem={({ item }) => <Text style={styles.row}>• {item.title}</Text>}      />    </View>  );} const styles = StyleSheet.create({  count: { fontWeight: 'bold', marginBottom: 8, color: '#E8820C' },  row: { padding: 8, fontSize: 15 },});
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس