Pressable — یک کامپوننت مدرن React Native برای پردازش لمسههاست که جایگزین TouchableHighlight، TouchableOpacity و TouchableWithoutFeedback منسوخ میشود. Pressable یک API واحد با تشخیص وضعیتهای pressed، hovered و focused ارائه میدهد. این کامپوننت در React Native 0.63 معرفی شد و Meta آن را برای تمامی پروژههای جدید توصیه میکند. در مورد کامپوننت در مستندات Meta بیشتر بخوانید.
اصولی
Pressable — یک کامپوننت React Native است که یک رابط واحد برای پردازش همه انواع لمسهها ارائه میدهد. بر خلاف سه کامپوننت متفاوت Touchable (TouchableHighlight، TouchableOpacity، TouchableWithoutFeedback)، Pressable تمام آنها را با یک سیستم انعطافپذیر وضعیت و سبکدهی جایگزین میشود.
این کامپوننت در React Native 0.63 (سپتامبر 2020) معرفی شد. به \u06AFزارش Meta (2026)، 70% از پروژههای جدید در React Native به جای کامپوننتهای Touchable از Pressable استفاده میکنند. Pressable مشکل اصلی Touchable را حل میکند — API پراکنده و نیاز به جابجایی بین کامپوننتها برای افکتهای مختلف.
بر خلاف TouchableOpacity که اثر فشار به صورت سخت تعیین شده (تغییر کدرت) است، Pressable یک تابع ارائه میدهد که وضعیت فعلی را دریافت میکند. توسعهدهنده خود تصمیم میگیرد که چگونه به لمسه واکنش نشان دهد: تغییر رنگ، مقیاس، سایه یا ترکیبی از افکتها. این کنترل کامل بر UX میدهد.
Pressable سه وضعیت تعامل را تعریف میکند: pressed (انگشت روی صفحه)، hovered (ماوس بالای عنصر در Web/TV)، focused (عنصر در کانون توجه صفحه کلید). هر وضعیت فراخوان مربوطه را فعال میکند و به تابع سبکها و تابع رندر فرزند ارسال میشود.
| وضعیت | شرط | واکنش معمولی |
|---|---|---|
| pressed | انگشت روی صفحه یا کلیک نگه داشته شده | تغییر کدرت، مقیاس، رنگ پس زمینه |
| hovered | ماوس بالای عنصر (Web، TV) | برجستگی، سایه، خط زیر |
| focused | عنصر در کانون توجه صفحه کلید | کنتور، حاشیه، تغییر رنگ |
مهم: hovered و focused تنها در سستمهایی که از اشارهگر پشتیبانی میکنند کار میکنند (Web، 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 ms)، 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 حداقل اندازه هدف لمسه را 44x44 نقطه توصیه میکند. hitSlop بدون تغییر اندازه ویزوال، امکان رعایت این نیاز را فراهم میکند.
hitSlop یک شیئه { top, bottom, left, right } یا یک عدد واحد برای تمام جوانب میپذیرد. مقادیر به پیکسلهای منطقی (dp/pt) تعیین میشوند. برای آیکونهای 24x24، hitSlop حداقل 10-12 از هر طرف برای دستیابی به هدف لمسه 44x44 توصیه میشود.
<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: API واحد برای همه انواع افکتها، دسترسی به وضعیت 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>
);
};مهم: برای انیمیشنها در Pressable از useNativeDriver: true استفاده کنید. این انیمیشن را به ریشه فرعی منتقل میکند و از افت کادر در فشارهای سریع جلوگیری میکند. برای 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 ms) تنظیم میشود. برای منوهای کانتکستی و کشیدن و رها کردن، onLongPress را با onPressIn ترکیب کنید.
بله، Pressable از وضعیت focused برای ناوبری صفحه کلید در Android TV، Apple TV و Web پشتیبانی میکند. برای نمایش فوکوس از سبکدهی از طریق { focused } استفاده کنید. در دستگاههای موبایل، وضعیت focused مربوط نیست.
نتایج
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید