Pressable é um componente moderno do React Native para manipular toques, substituindo os obsoletos TouchableHighlight, TouchableOpacity e TouchableWithoutFeedback. O Pressable fornece uma API unificada com detecção dos estados pressed, hovered e focused. O componente foi introduzido no React Native 0.63 e é recomendado pela Meta para todos os novos projetos. Saiba mais em documentação da Meta.
Principais pontos
Pressable é um componente React Native que fornece uma interface unificada para manipular todos os tipos de toques. Ao contrário de três componentes Touchable diferentes (TouchableHighlight, TouchableOpacity, TouchableWithoutFeedback), o Pressable substitui todos eles com um sistema flexível de estados e estilos.
O componente foi introduzido no React Native 0.63 (setembro de 2020). De acordo com a Meta (2026), 70% dos novos projetos em React Native usam Pressable em vez dos componentes Touchable. O Pressable resolve o problema principal do Touchable — uma API fragmentada e a necessidade de alternar entre componentes para efeitos diferentes.
Ao contrário do TouchableOpacity, onde o efeito de pressão é fixo (mudança de opacidade), o Pressable fornece uma função que recebe o estado atual. O desenvolvedor decide como responder visualmente a um pressionamento: alterar cor, escala, sombra ou uma combinação de efeitos. Isso dá controle total sobre a UX.
Pressable define três estados de interação: pressed (dedo na tela), hovered (cursor sobre o elemento na Web/TV), focused (elemento em foco do teclado). Cada estado ativa o callback correspondente e é passado para a função de estilo e para a função de renderização filha.
| Estado | Condição | Reação típica |
|---|---|---|
| pressed | Dedo na tela ou clique pressionado | Alteração de opacidade, escala ou cor de fundo |
| hovered | Cursor sobre o elemento (Web, TV) | Destaque, sombra, sublinhado |
| focused | Elemento em foco do teclado | Contorno, borda, mudança de cor |
Importante: hovered e focused funcionam apenas em plataformas com suporte a ponteiro (Web, Android TV, Apple TV). Em dispositivos móveis, apenas pressed está disponível. Para aplicativos multiplataforma, projete reações visuais considerando essa limitação.
<Pressable
style={({ pressed }) => [
styles.button,
pressed && styles.buttonPressed,
]}
onPress={handlePress}>
{({ pressed }) => (
<Text style={pressed ? styles.textPressed : styles.text}>
{pressed ? 'Release' : 'Press'}
</Text>
)}
</Pressable>A API do Pressable inclui quatro callbacks principais: onPress (pressionamento completo com liberação), onLongPress (pressionamento longo), onPressIn (início do toque) e onPressOut (fim do toque). A combinação de onPressIn e onPressOut permite criar animações personalizadas.
Props adicionais: delayLongPress (atraso do pressionamento longo, padrão 500 ms), pressRetentionOffset (área além da qual o pressionamento é cancelado), android_ripple (efeito ripple no Android). Nota: Ripple funciona apenas no Android 5+.
<Pressable
onPress={() => console.log('Pressionado')}
onLongPress={() => console.log('Pressão longa')}
onPressIn={() => console.log('Dedo para baixo')}
onPressOut={() => console.log('Dedo para cima')}
delayLongPress={300}
android_ripple={{ color: 'rgba(0,0,0,0.1)', borderless: false }}
style={styles.button}>
<Text>Press me</Text>
</Pressable>onPress só é chamado se o dedo for levantado dentro da área do componente (considerando pressRetentionOffset). Se o usuário mover o dedo para fora dos limites, onPress não é acionado, evitando pressionamentos falsos. onPressOut é chamado em qualquer caso ao liberar.
hitSlop é uma prop do Pressable que estende a área de toque além dos limites visíveis do componente. Isso é crítico para elementos pequenos: ícones, caixas de seleção, botões de opção. A Apple HIG recomenda um tamanho mínimo de alvo de toque de 44×44 pontos. O hitSlop permite atender a esse requisito sem alterar o tamanho visual.
hitSlop aceita um objeto { top, bottom, left, right } ou um único número para todos os lados. Os valores são especificados em pixels lógicos (dp/pt). Para ícones de 24×24, recomenda-se um hitSlop de pelo menos 10–12 de cada lado para atingir o alvo de toque de 44×44.
<Pressable
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
onPress={handleIconPress}
style={styles.iconButton}>
<Icon name="star" size={24} />
</Pressable>pressRetentionOffset — o inverso do hitSlop: define a área na qual o usuário pode sair dos limites do componente sem cancelar o pressionamento. Por padrão, é igual ao hitSlop. Se precisar que o pressionamento persista ao sair dos limites, aumente pressRetentionOffset.
Pressable vs Touchable — uma questão chave ao escolher um componente para manipular toques. TouchableOpacity, TouchableHighlight e TouchableWithoutFeedback são componentes obsoletos que não serão removidos, mas não receberão novos recursos. A Meta recomenda Pressable para novos projetos.
Principais vantagens do Pressable: API unificada para todos os tipos de efeitos, acesso ao estado pressed para estilização personalizada, suporte aos estados hovered/focused, hitSlop e pressRetentionOffset, callback onLongPress sem configuração adicional. TouchableOpacity é adequado apenas para alterações simples de opacidade.
| Cenário | Touchable | Pressable |
|---|---|---|
| Pressionamento simples | TouchableOpacity | Pressable + opacity no style |
| Destaque de fundo | TouchableHighlight | Pressable + backgroundColor |
| Sem efeito visual | TouchableWithoutFeedback | Pressable com style vazio |
| Pressionamento longo | onLongPress em qualquer Touchable | onLongPress no Pressable |
| Animação personalizada | Animated + onPressIn/Out | Pressable + useAnimatedStyle |
| Ripple no Android | TouchableNativeFeedback | Pressable + android_ripple |
Pressable permite criar elementos interativos complexos com código mínimo. Abaixo está um exemplo de um botão animado com mudança de escala ao pressionar e efeito ripple no Android. Esse botão substitui a combinação 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>
);
};Importante: use useNativeDriver: true para animações no Pressable. Isso transfere a animação para a thread nativa, evitando quedas de quadros durante pressionamentos rápidos. O driver nativo é suportado para transform e opacity em todas as plataformas.
Perguntas frequentes
Não, Pressable tem uma API diferente. TouchableOpacity aplica opacidade automaticamente ao pressionar. Pressable requer especificação explícita do estilo através de uma função de estado. A substituição é trivial: passe style={({ pressed }) => [{ opacity: pressed ? 0.5 : 1 }]}.
Use a prop android_ripple com um objeto { color, borderless }. A cor do ripple é especificada em formato rgba. Para botões redondos, use borderless: true. Ripple funciona apenas no Android 5+. No iOS, use animação personalizada.
Pressable tem proteção integrada contra pressionamentos acidentais durante a rolagem. Se o usuário rolar uma lista, onPress não é chamado. Esse comportamento pode ser configurado via pressRetentionOffset e delayPressIn.
Use a prop onLongPress — suporte integrado para pressionamento longo. O atraso é configurável via delayLongPress (padrão 500 ms). Para menus de contexto e arrastar e soltar, combine onLongPress com onPressIn.
Sim, Pressable suporta o estado focused para navegação por teclado no Android TV, Apple TV e Web. Use estilização via { focused } para exibir o foco. Em dispositivos móveis, o estado focused não é aplicável.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também