Pressable — 这是什么,React Native 中的按压处理

作者: IT Sectr 发布日期: 2026-07-06 阅读时间: 10 分钟

Pressable — 是一个现代化的 React Native 组件,用于处理触摸操作,取代已过时的 TouchableHighlight、TouchableOpacity 和 TouchableWithoutFeedback。Pressable 提供统一的 API,支持 pressed、hovered 和 focused 状态的检测。该组件在 React Native 0.63 中引入,并被 Meta 推荐用于所有新项目。有关该组件的更多信息,请参阅 Meta 文档

主要内容

  • Pressable — 通用的触摸处理组件,支持 pressed、hovered、focused 状态
  • API 包括 onPress、onLongPress、onPressIn、onPressOut 回调函数和基于状态的样式函数
  • hitSlop 将触摸区域扩展到组件可见边界之外,以提升用户体验
  • 替换 Touchable — Pressable 将所有 Touchable 组件的 API 统一为一个灵活的接口
  • 无障碍 — 组件支持 ARIA 角色,并自动处理 VoiceOver 和 TalkBack

什么是 Pressable?

Pressable — 是一个 React Native 组件,提供统一的接口来处理所有类型的触摸。与三种不同的 Touchable 组件(TouchableHighlight、TouchableOpacity、TouchableWithoutFeedback)不同,Pressable 用一个具有灵活状态和样式系统的组件取代它们全部。

该组件在 React Native 0.63(2020 年 9 月)中引入。根据 Meta 的数据(2026),React Native 上 70% 的新项目使用 Pressable 代替 Touchable 组件。Pressable 解决了 Touchable 的主要问题——API 碎片化以及为了不同效果而需要在组件之间切换的问题。

Pressable 的设计理念

TouchableOpacity 不同,后者的按压效果是固定的(改变透明度),Pressable 提供一个接收当前状态的函数。开发者自己决定如何在视觉上响应触摸:改变颜色、缩放、阴影或效果的组合。这提供了对用户体验的完全控制。

Pressable 状态:pressed、hovered、focused

Pressable 定义了三种交互状态:pressed(手指在屏幕上)、hovered(光标在元素上方,在 Web/TV 上)、focused(元素在键盘聚焦中)。每个状态会触发相应的回调函数,并传递给样式函数和子元素的渲染函数。

状态条件典型响应
pressed手指在屏幕上或点击按下改变透明度、缩放、背景颜色
hovered光标在元素上方(Web、TV)高亮、阴影、下划线
focused元素在键盘聚焦中外框、边框、颜色变化

重要:hovered 和 focused 仅在支持指示设备的平台上工作(Web、Android TV、Apple TV)。在移动设备上,仅可使用 pressed。对于跨平台应用程序,设计视觉响应时应考虑这一限制。

js
<Pressable
  style={({ pressed }) => [
    styles.button,
    pressed && styles.buttonPressed,
  ]}
  onPress={handlePress}>
  {({ pressed }) => (
    <Text style={pressed ? styles.textPressed : styles.text}>
      {pressed ? 'Release' : 'Press'}
    </Text>
  )}
</Pressable>

Pressable 的 API 和回调函数

Pressable API 包含四个主要回调函数:onPress(完整按压并释放)、onLongPress(长按)、onPressIn(触摸开始)和 onPressOut(触摸结束)。onPressIn 和 onPressOut 的组合可以创建自定义动画。

额外的 props:delayLongPress(长按延迟,默认 500 毫秒)、pressRetentionOffset(超出此区域按压取消)、android_ripple(Android 上的 ripple 效果)。重要:Ripple 仅在 Android 5+ 上工作。

js
<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:扩展触摸区域

hitSlop — 是 Pressable 的一个 prop,用于将触摸区域扩展到组件可见边界之外。这对于小元素至关重要:图标、复选框、单选按钮。Apple HIG 建议触摸目标的最小尺寸为 44x44 点。hitSlop 可以在不改变视觉尺寸的情况下满足这一要求。

hitSlop 接受一个对象 { top, bottom, left, right } 或一个单一数值针对所有边。值以逻辑像素(dp/pt)指定。对于 24x24 的图标,建议每边 hitSlop 至少 10-12,以达到 44x44 的触摸目标。

js
<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:什么时候迁移

Pressable 与 Touchable — 选择触摸处理组件时的关键问题。TouchableOpacity、TouchableHighlight 和 TouchableWithoutFeedback 是已过时的组件,它们不会被删除,但不会获得新功能。Meta 建议新项目使用 Pressable。

Pressable 的主要优势:统一的 API 支持所有类型的效果、可访问 pressed 状态以进行自定义样式、支持 hovered/focused 状态、hitSlop 和 pressRetentionOffset、无需额外配置即可使用 onLongPress 回调函数。TouchableOpacity 仅适合简单的透明度变化。

场景TouchablePressable
简单按压TouchableOpacityPressable + style 中的 opacity
背景高亮TouchableHighlightPressable + backgroundColor
无视觉效果TouchableWithoutFeedback带空 style 的 Pressable
长按任何 Touchable 上的 onLongPressPressable 上的 onLongPress
自定义动画Animated + onPressIn/OutPressable + useAnimatedStyle
Android 上的 RippleTouchableNativeFeedbackPressable + android_ripple

Pressable 使用示例

Pressable 可以用最少的代码创建复杂的交互元素。下面是一个动画按钮的示例,在按压时改变缩放并在 Android 上显示 ripple 效果。这样的按钮可以替代 TouchableOpacity + Animated 的组合。

js
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 替代 TouchableOpacity 吗?

不能,Pressable 有不同的 API。TouchableOpacity 在按压时自动应用透明度。Pressable 需要通过状态函数 明确指定样式。替换很简单:传递 style={({ pressed }) => [{ opacity: pressed ? 0.5 : 1 }]}。

如何创建像 Material Design 中的 ripple 效果?

使用 android_ripple prop,带一个 { color, borderless } 对象。Ripple 颜色以 rgba 格式指定。对于圆形按钮,使用 borderless: true。Ripple 仅在 Android 5+ 上工作。在 iOS 上使用自定义动画。

为什么快速滚动时 onPress 不反应?

Pressable 具有内置防误触保护。如果用户滚动列表,onPress 不会被调用。可以通过 pressRetentionOffset 和 delayPressIn 配置此行为。

如何使用 Pressable 监听长按操作?

使用 onLongPress prop——内置支持长按。延迟通过 delayLongPress(默认 500 毫秒)配置。对于上下文菜单和拖拽,将 onLongPress 与 onPressIn 组合使用。

Pressable 支持键盘导航吗?

是的,Pressable 在 Android TV、Apple TV 和 Web 上支持 focused 状态的键盘导航。使用 { focused } 进行样式设置以显示聚焦。在移动设备上,focused 状态不相关。

总结

  • Pressable — 通用的 React Native 触摸处理组件,替代 TouchableOpacity、TouchableHighlight 和 TouchableWithoutFeedback
  • 状态 pressed、hovered、focused 传递给样式函数,可以为每个场景自定义响应
  • hitSlop 将触摸目标扩展到 44x44 点而不改变视觉尺寸,提升小元素上的用户体验
  • API 包含 onPress、onLongPress、onPressIn、onPressOut,可通过 delayLongPress 配置延迟
  • android_ripple 在 Android 5+ 上添加 Material Design ripple 效果,可配置颜色和形状
  • 从 Touchable 迁移 需要将自动效果替换为通过状态函数 明确样式设置
  • Animated + Pressable 使用 useNativeDriver 创建流畅的按压动画,保证性能

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读