18. Жесты (Gesture Handler)
react-native-gesture-handler — нативная обработка жестов. Работает в нативном потоке без JS bridge.
Установка
Заголовок раздела «Установка»npx expo install react-native-gesture-handler react-native-reanimated// Обязательно в начале App.tsx!import 'react-native-gesture-handler';import { GestureHandlerRootView } from 'react-native-gesture-handler';
export default function App() { return ( <GestureHandlerRootView style={{ flex: 1 }}> <Navigation /> </GestureHandlerRootView> );}Gesture API v2 (современный)
Заголовок раздела «Gesture API v2 (современный)»import { Gesture, GestureDetector } from 'react-native-gesture-handler';import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';
function DraggableBox() { const offsetX = useSharedValue(0); const offsetY = useSharedValue(0);
const panGesture = Gesture.Pan() .onUpdate((event) => { offsetX.value = event.translationX; offsetY.value = event.translationY; }) .onEnd(() => { offsetX.value = withSpring(0); offsetY.value = withSpring(0); });
const animatedStyle = useAnimatedStyle(() => ({ transform: [ { translateX: offsetX.value }, { translateY: offsetY.value }, ], }));
return ( <GestureDetector gesture={panGesture}> <Animated.View style={[styles.box, animatedStyle]} /> </GestureDetector> );}Pinch to Zoom
Заголовок раздела «Pinch to Zoom»function ZoomableImage() { const scale = useSharedValue(1); const savedScale = useSharedValue(1);
const pinchGesture = Gesture.Pinch() .onUpdate((e) => { scale.value = savedScale.value * e.scale; }) .onEnd(() => { savedScale.value = scale.value; if (scale.value < 1) { scale.value = withSpring(1); savedScale.value = 1; } });
const style = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }] }));
return ( <GestureDetector gesture={pinchGesture}> <Animated.Image source={{ uri: imageUrl }} style={[styles.image, style]} /> </GestureDetector> );}Swipeable (удаление элементов)
Заголовок раздела «Swipeable (удаление элементов)»import Swipeable from 'react-native-gesture-handler/Swipeable';
function SwipeableItem({ item, onDelete }) { const renderRightActions = () => ( <TouchableOpacity style={styles.deleteAction} onPress={onDelete}> <Text style={{ color: '#fff' }}>Удалить</Text> </TouchableOpacity> );
return ( <Swipeable renderRightActions={renderRightActions}> <View style={styles.item}><Text>{item.title}</Text></View> </Swipeable> );}Комбинированные жесты
Заголовок раздела «Комбинированные жесты»// Одновременно pan + pinch (для карты)const composed = Gesture.Simultaneous(panGesture, pinchGesture);
// Эксклюзивно (первый матч)const exclusive = Gesture.Exclusive(longPressGesture, tapGesture);
// Последовательноconst sequence = Gesture.Race(longPressGesture, panGesture);