Pressable هو مكون حديث في React Native لمعالجة اللمسات، ليحل محل TouchableHighlight وTouchableOpacity وTouchableWithoutFeedback القديمة. يوفر Pressable واجهة برمجة تطبيقات موحدة مع كشف الحالات pressed وhovered وfocused. تم تقديم المكون في React Native 0.63 وتوصي به Meta لجميع المشاريع الجديدة. اعرف المزيد في توثيق Meta.
النقاط الرئيسية
Pressable هو مكون React Native يوفر واجهة موحدة لمعالجة جميع أنواع اللمسات. على عكس ثلاثة مكونات Touchable مختلفة (TouchableHighlight وTouchableOpacity وTouchableWithoutFeedback)، يحل Pressable محلها جميعاً بنظام مرن للحالات والتصميم.
تم تقديم المكون في React Native 0.63 (سبتمبر 2020). وفقاً لـ Meta (2026)، 70% من المشاريع الجديدة على React Native تستخدم Pressable بدلاً من مكونات Touchable. يحل Pressable المشكلة الرئيسية لـ Touchable — واجهة برمجة تطبيقات مجزأة والحاجة للتبديل بين المكونات لتأثيرات مختلفة.
على عكس TouchableOpacity، حيث يكون تأثير الضغط ثابتاً (تغيير الشفافية)، يوفر Pressable دالة تستقبل الحالة الحالية. يقرر المطور كيفية الاستجابة بصرياً للضغط: تغيير اللون أو الحجم أو الظل أو مزيج من التأثيرات. هذا يمنح تحكماً كاملاً في تجربة المستخدم.
Pressable يحدد ثلاث حالات تفاعل: pressed (الإصبع على الشاشة)، hovered (المؤشر فوق العنصر على الويب/التلفاز)، focused (العنصر في بؤرة التركيز بلوحة المفاتيح). كل حالة تشغل الاستدعاء المناسب وتمرر إلى دالة التصميم ودالة التصيير الفرعية.
| الحالة | الشرط | رد الفعل النموذجي |
|---|---|---|
| pressed | الإصبع على الشاشة أو النقر مستمر | تغيير الشفافية أو الحجم أو لون الخلفية |
| hovered | المؤشر فوق العنصر (ويب، تلفاز) | تمييز، ظل، تسطير |
| focused | العنصر في بؤرة التركيز بلوحة المفاتيح | مخطط تفصيلي، حد، تغيير لون |
مهم: hovered وfocused يعملان فقط على المنصات التي تدعم المؤشر (ويب، Android TV، Apple TV). على الأجهزة المحمولة، يتوفر pressed فقط. للتطبيقات متعددة المنصات، صمم ردود الفعل البصرية مع مراعاة هذا القيد.
<Pressable
style={({ pressed }) => [
styles.button,
pressed && styles.buttonPressed,
]}
onPress={handlePress}>
{({ pressed }) => (
<Text style={pressed ? styles.textPressed : styles.text}>
{pressed ? 'Release' : 'Press'}
</Text>
)}
</Pressable>API Pressable تتضمن أربعة استدعاءات رئيسية: onPress (ضغط كامل مع تحرير)، onLongPress (ضغط طويل)، onPressIn (بداية اللمس)، onPressOut (نهاية اللمس). يتيح الجمع بين onPressIn وonPressOut إنشاء رسوم متحركة مخصصة.
خصائص إضافية: delayLongPress (تأخير الضغط الطويل، افتراضياً 500 مللي ثانية)، pressRetentionOffset (المنطقة التي تلغي الضغط خارجها)، android_ripple (تأثير ripple على Android). ملاحظة: Ripple يعمل فقط على Android 5+.
<Pressable
onPress={() => console.log('مضغوط')}
onLongPress={() => console.log('ضغط مطول')}
onPressIn={() => console.log('إصبع لأسفل')}
onPressOut={() => console.log('إصبع لأعلى')}
delayLongPress={300}
android_ripple={{ color: 'rgba(0,0,0,0.1)', borderless: false }}
style={styles.button}>
<Text>Press me</Text>
</Pressable>onPress يُستدعى فقط إذا رفع الإصبع داخل منطقة المكون (مع مراعاة pressRetentionOffset). إذا حرك المستخدم إصبعه خارج الحدود، لا يتم تشغيل onPress، مما يمنع الضغطات الخاطئة. onPressOut يُستدعى في أي حال عند التحرير.
hitSlop هي خاصية Pressable توسع منطقة اللمس خارج الحدود المرئية للمكون. هذا ضروري للعناصر الصغيرة: الأيقونات، مربعات الاختيار، أزرار الاختيار. توصي Apple HIG بحجم هدف لمس أدنى 44×44 نقطة. يسمح hitSlop بالامتثال لهذا المطلب دون تغيير الحجم المرئي.
hitSlop يقبل كائن { top, bottom, left, right } أو رقماً واحداً لجميع الجوانب. تُحدد القيم بالبكسل المنطقي (dp/pt). للأيقونات 24×24، يُوصى بـ hitSlop لا يقل عن 10–12 من كل جانب لتحقيق هدف لمس 44×44.
<Pressable
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
onPress={handleIconPress}
style={styles.iconButton}>
<Icon name="star" size={24} />
</Pressable>pressRetentionOffset — عكس hitSlop: يحدد المنطقة التي يمكن للمستخدم الخروج فيها خارج حدود المكون دون إلغاء الضغط. افتراضياً يساوي hitSlop. إذا كنت بحاجة إلى استمرار الضغط عند الخروج خارج الحدود، قم بزيادة pressRetentionOffset.
Pressable ضد Touchable — سؤال رئيسي عند اختيار مكون لمعالجة اللمسات. TouchableOpacity وTouchableHighlight وTouchableWithoutFeedback هي مكونات قديمة لن تُحذف لكنها لن تتلقى ميزات جديدة. توصي Meta باستخدام Pressable للمشاريع الجديدة.
المزايا الرئيسية لـ Pressable: واجهة برمجة تطبيقات موحدة لجميع أنواع التأثيرات، الوصول إلى حالة pressed للتصميم المخصص، دعم حالات hovered/focused، hitSlop وpressRetentionOffset، استدعاء onLongPress دون تهيئة إضافية. TouchableOpacity مناسب فقط لتغييرات الشفافية البسيطة.
| السيناريو | Touchable | Pressable |
|---|---|---|
| ضغط بسيط | TouchableOpacity | Pressable + opacity في style |
| تمييز الخلفية | TouchableHighlight | Pressable + backgroundColor |
| بدون تأثير بصري | TouchableWithoutFeedback | Pressable مع style فارغ |
| ضغط طويل | onLongPress على أي Touchable | onLongPress على Pressable |
| رسوم متحركة مخصصة | Animated + onPressIn/Out | Pressable + useAnimatedStyle |
| Ripple على Android | TouchableNativeFeedback | Pressable + android_ripple |
Pressable يسمح بإنشاء عناصر تفاعلية معقدة بأقل كود. فيما يلي مثال لزر متحرك مع تغيير الحجم عند الضغط وتأثير ripple على Android. هذا الزر يحل محل مجموعة TouchableOpacity + Animated.
const AnimatedButton = ({ title, onPress }) => {
const scale = React.useRef(new Animated.Value(1)).current;
const handlePressIn = () => {
Animated.spring(scale, {
toValue: 0.96,
useNativeDriver: true,
}).start();
};
const handlePressOut = () => {
Animated.spring(scale, {
toValue: 1,
friction: 3,
useNativeDriver: true,
}).start();
};
return (
<Pressable
onPress={onPress}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
android_ripple={{ color: 'rgba(255,255,255,0.3)' }}
style={styles.button}>
<AnimatedView style={[styles.inner, { transform: [{ scale }] }]}>
<Text style={styles.text}>{title}</Text>
</AnimatedView>
</Pressable>
);
};مهم: استخدم useNativeDriver: true للرسوم المتحركة في Pressable. هذا ينقل الرسوم المتحركة إلى الخيط الأصلي، مما يمنع فقدان الإطارات أثناء الضغطات السريعة. مشغل native مدعوم لـ transform وopacity على جميع المنصات.
الأسئلة الشائعة
لا، Pressable لديه API مختلف. TouchableOpacity يطبق الشفافية تلقائياً عند الضغط. Pressable يتطلب تحديد التصميم صراحة عبر دالة الحالة. الاستبدال بسيط: مرر style={({ pressed }) => [{ opacity: pressed ? 0.5 : 1 }]}.
استخدم الخاصية android_ripple مع كائن { color, borderless }. يُحدد لون ripple بتنسيق rgba. للأزرار الدائرية، استخدم borderless: true. Ripple يعمل فقط على Android 5+. على iOS، استخدم رسوماً متحركة مخصصة.
Pressable لديه حماية مدمجة ضد الضغطات العرضية أثناء التمرير. إذا مرر المستخدم قائمة، لا يتم استدعاء onPress. يمكن تهيئة هذا السلوك عبر pressRetentionOffset وdelayPressIn.
استخدم الخاصية onLongPress — دعم مدمج للضغط الطويل. يتم ضبط التأخير عبر delayLongPress (افتراضياً 500 مللي ثانية). للقوائم السياقية والسحب والإفلات، ادمج onLongPress مع onPressIn.
نعم، Pressable يدعم حالة focused للتنقل بلوحة المفاتيح على Android TV وApple TV والويب. استخدم التصميم عبر { focused } لعرض التركيز. على الأجهزة المحمولة، حالة focused غير قابلة للتطبيق.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.