📌  相关文章
📜  使用 react native expo 进行手势处理 - Javascript (1)

📅  最后修改于: 2023-12-03 14:49:46.055000             🧑  作者: Mango

使用 React Native Expo 进行手势处理

在 React Native 应用中,处理用户手势是常见需求之一,因为用户手势可以大大提高应用的交互体验。React Native 官方提供了很多原始的手势处理 API,但使用 Expo 的手势处理库可以更方便地实现手势处理。

在本篇教程中,我们将使用 Expo 的手势处理库,介绍如何在 React Native 应用中处理各种手势,比如手指滑动、捏合和旋转等。

准备工作

在开始之前,请先确保已经安装了 Expo CLI,并新建了一个 Expo 项目。

如果尚未安装,可以使用以下命令进行安装:

npm install -g expo-cli

创建 Expo 项目的命令如下:

expo init my-project

然后选择模板,推荐选择 "Blank"。

安装手势库

为了处理各种手势,我们需要使用 Expo 的手势处理库。在 Expo 项目中,安装手势库非常方便,只需在命令行中输入以下命令:

expo install react-native-gesture-handler
使用手势处理库

使用手势处理库需要先导入库:

import { PanGestureHandler, PinchGestureHandler, RotationGestureHandler, TapGestureHandler, State } from 'react-native-gesture-handler';

在本教程中,我们会分别介绍如何使用 PanGestureHandlerPinchGestureHandlerRotationGestureHandlerTapGestureHandler 处理手势。

拖动手势

使用 PanGestureHandler 可以处理拖动手势。下面是一个例子,实现了一个简单的拖动小球的效果:

import React, { useRef } from 'react';
import { StyleSheet, View, Animated, Text } from 'react-native';
import { PanGestureHandler, State } from 'react-native-gesture-handler';

export default function PanGestureHandlerExample() {
  const translateX = useRef(new Animated.Value(0)).current;
  const translateY = useRef(new Animated.Value(0)).current;

  const onGestureEvent = Animated.event(
    [
      {
        nativeEvent: {
          translationX: translateX,
          translationY: translateY,
        },
      },
    ],
    { useNativeDriver: true }
  );

  const onHandlerStateChange = event => {
    if (event.nativeEvent.state === State.END) {
      Animated.spring(translateX, { toValue: 0, useNativeDriver: true }).start();
      Animated.spring(translateY, { toValue: 0, useNativeDriver: true }).start();
    }
  };

  return (
    <View style={styles.container}>
      <PanGestureHandler
        onGestureEvent={onGestureEvent}
        onHandlerStateChange={onHandlerStateChange}>
        <Animated.View style={[styles.ball, { transform: [{ translateX }, { translateY }] }]} />
      </PanGestureHandler>
    </View>
  );
}

const BALL_SIZE = 70;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  ball: {
    width: BALL_SIZE,
    height: BALL_SIZE,
    borderRadius: BALL_SIZE / 2,
    backgroundColor: '#5ece7b',
  },
});

其中,我们使用了 Animated.Value 来管理 translateXtranslateY 的值。在手势发生变化时,我们动态更新 translateXtranslateY 的值。当手势结束时,我们使用 Animated.spring() 方法让小球回到初始位置。

缩放手势

使用 PinchGestureHandler 可以实现缩放手势。下面是一个例子,实现了一个可缩放小球的效果:

import React, { useRef } from 'react';
import { StyleSheet, View, Animated } from 'react-native';
import { PinchGestureHandler, State } from 'react-native-gesture-handler';

export default function PinchGestureHandlerExample() {
  const scale = useRef(new Animated.Value(1)).current;

  const onGestureEvent = Animated.event(
    [
      {
        nativeEvent: {
          scale: scale,
        },
      },
    ],
    { useNativeDriver: true }
  );

  const onHandlerStateChange = event => {
    if (event.nativeEvent.oldState === State.ACTIVE) {
      Animated.spring(scale, { toValue: 1, useNativeDriver: true }).start();
    }
  };

  return (
    <View style={styles.container}>
      <PinchGestureHandler onGestureEvent={onGestureEvent} onHandlerStateChange={onHandlerStateChange}>
        <Animated.View style={[styles.ball, { transform: [{ scale }] }]} />
      </PinchGestureHandler>
    </View>
  );
}

const BALL_SIZE = 70;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  ball: {
    width: BALL_SIZE,
    height: BALL_SIZE,
    borderRadius: BALL_SIZE / 2,
    backgroundColor: '#5ece7b',
  },
});

其中,我们使用了 Animated.Value 来管理 scale 的值。在手势发生变化时,我们动态更新 scale 的值。当手势结束时,我们使用 Animated.spring() 方法将 scale 的值回到 1。

旋转手势

使用 RotationGestureHandler 可以实现旋转手势。下面是一个例子,实现了一个可旋转小球的效果:

import React, { useRef } from 'react';
import { StyleSheet, View, Animated } from 'react-native';
import { RotationGestureHandler, State } from 'react-native-gesture-handler';

export default function RotationGestureHandlerExample() {
  const rotate = useRef(new Animated.Value(0)).current;

  const onGestureEvent = Animated.event(
    [{ nativeEvent: { rotation: rotate } }],
    { useNativeDriver: true }
  );

  const onHandlerStateChange = event => {
    if (event.nativeEvent.oldState === State.ACTIVE) {
      Animated.spring(rotate, { toValue: 0, useNativeDriver: true }).start();
    }
  };

  return (
    <View style={styles.container}>
      <RotationGestureHandler onGestureEvent={onGestureEvent} onHandlerStateChange={onHandlerStateChange}>
        <Animated.View style={[styles.ball, { transform: [{ rotate: `${rotate}deg` }] }]} />
      </RotationGestureHandler>
    </View>
  );
}

const BALL_SIZE = 70;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  ball: {
    width: BALL_SIZE,
    height: BALL_SIZE,
    borderRadius: BALL_SIZE / 2,
    backgroundColor: '#5ece7b',
  },
});

其中,我们使用了 Animated.Value 来管理 rotate 的值。在手势发生变化时,我们动态更新 rotate 的值。当手势结束时,我们使用 Animated.spring() 方法将 rotate 的值回到初始状态。

点击手势

使用 TapGestureHandler 可以实现点击手势。下面是一个例子,每次点击小球,都会显示一个计数器的数值:

import React, { useRef, useState } from 'react';
import { StyleSheet, View, Text } from 'react-native';
import { TapGestureHandler, State } from 'react-native-gesture-handler';

export default function TapGestureHandlerExample() {
  const [count, setCount] = useState(0);

  const onHandlerStateChange = event => {
    if (event.nativeEvent.state === State.ACTIVE) {
      setCount(count => count + 1);
    }
  };

  return (
    <View style={styles.container}>
      <TapGestureHandler onHandlerStateChange={onHandlerStateChange}>
        <View style={styles.ball}>
          <Text style={styles.text}>{count}</Text>
        </View>
      </TapGestureHandler>
    </View>
  );
}

const BALL_SIZE = 70;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  ball: {
    width: BALL_SIZE,
    height: BALL_SIZE,
    borderRadius: BALL_SIZE / 2,
    backgroundColor: '#5ece7b',
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    fontSize: 28,
    fontWeight: 'bold',
    color: 'white',
  },
});

其中,我们在 onHandlerStateChange 回调函数中,每次点击小球时,都会将计数器加一。

总结

在本篇教程中,我们介绍了如何使用 Expo 的手势处理库,实现各种手势,比如拖动、缩放、旋转和点击等。希望本篇教程能对您有所帮助。