Pressables and Touch
Touch targets, press feedback, and patterns that keep taps reliable on phones.
Busque em todas as páginas da documentação
Touch targets, press feedback, and patterns that keep taps reliable on phones.
Pressable is the preferred primitive for custom buttons - more flexible than legacy Touchables.
import { Pressable, Text } from "react-native";
<Pressable onPress={onSave}>
<Text>Save</Text>
</Pressable>Style can be a function of { pressed } for opacity or color feedback without extra state.
<Pressable
onPress={onPress}
style={({ pressed }) => [{ opacity: pressed ? 0.7 : 1 }, styles.btn]}
>
<Text>Continue</Text>
</Pressable>Expand the touch box without changing visuals - critical for small icons.
<Pressable hitSlop={12} onPress={onClose}>
<Icon name="x" />
</Pressable>disabled blocks press handlers and should pair with muted styles and accessibilityState.
<Pressable disabled={isPending} onPress={onSubmit} accessibilityState={{ disabled: isPending }}>
<Text>Submit</Text>
</Pressable>Still common in older codebases. Prefer Pressable for new work unless a library requires Touchable.
import { TouchableOpacity, Text } from "react-native";
<TouchableOpacity activeOpacity={0.7} onPress={onPress}>
<Text>Legacy button</Text>
</TouchableOpacity>RN Button is a thin system control - fine for prototypes, limited for design systems.
import { Button } from "react-native";
<Button title="OK" onPress={onOk} />onLongPress opens context menus and secondary actions.
<Pressable onPress={onOpen} onLongPress={onShowMenu}>
<Text>{title}</Text>
</Pressable>Tune how long the finger must stay down before long-press fires.
<Pressable delayLongPress={400} onLongPress={onShowMenu}>
<Row />
</Pressable>Avoid wrapping pressable rows in another pressable parent. If you must nest, stop propagation patterns carefully - prefer separate hit targets.
// Prefer sibling actions over Pressable inside Pressable rows
<View style={{ flexDirection: "row" }}>
<Pressable onPress={onOpen} style={{ flex: 1 }}><Text>{title}</Text></Pressable>
<Pressable onPress={onDelete}><Text>Delete</Text></Pressable>
</View>Allow the finger to drift slightly while still counting as a press.
<Pressable pressRetentionOffset={20} onPress={onPress}>
<Text>Drag-tolerant</Text>
</Pressable>Material ripple on Android via the android_ripple prop.
<Pressable
android_ripple={{ color: "#dbeafe" }}
onPress={onPress}
style={styles.row}
>
<Text>Row</Text>
</Pressable>Light haptics improve perceived quality on supported devices (expo-haptics).
import * as Haptics from "expo-haptics";
async function onPress() {
await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
doAction();
}Guard async presses so double-taps do not fire two mutations.
const busy = useRef(false);
async function onPress() {
if (busy.current) return;
busy.current = true;
try {
await submit();
} finally {
busy.current = false;
}
}Expose the control as a button to VoiceOver/TalkBack and give it a spoken name.
<Pressable
accessibilityRole="button"
accessibilityLabel="Save profile"
onPress={onSave}
>
<Icon name="check" />
</Pressable>When using React Native Gesture Handler, wrap the app (Expo Router does this in templates) so gestures and native navigators cooperate.
// Expo Router templates already wrap with GestureHandlerRootView.
// Bare RN: import { GestureHandlerRootView } from "react-native-gesture-handler";
// return <GestureHandlerRootView style={{ flex: 1 }}><App /></GestureHandlerRootView>;Stack versions: React 19.2.3 · React Native 0.86.0 · Expo SDK 57
Revisado por Chris St. John·Última atualização: 18 de jul. de 2026