首页 > 解决方案 > 屏幕上的多个 panresponder 管理不同的区域(同时)

问题描述

有什么办法可以同时使用两个 Panresponder 而不会相互干扰?

我想创建一个应用程序,可以在特定区域同时更改两个样方的位置:蓝色样方应该只能在蓝色区域中移动,而灰色样方应该只能在白色区域中移动。(图片:在这里你可以看到我的应用程序屏幕)但问题是触摸事件相互干扰。

到目前为止,这是我的代码:

import React, { useState } from "react";
import {
  StyleSheet,
  Text,
  View,
  Animated,
  PanResponder,
  Dimensions,
} from "react-native";

const phoneWidth = Dimensions.get("window").width;

export default function App() {
  const ball = useState(new Animated.ValueXY())[0];
  const panResponder = useState(
    new PanResponder.create({
      onStartShouldSetPanResponder: () => false,
      onMoveShouldSetPanResponder: () => true,
      onPanResponderGrant: (_, gesture) => {
        ball.setOffset({
          x: ball.x._value,
          y: ball.y._value,
        });
      },
      onPanResponderMove: (_, gesture) => {
        console.log(gesture);
        if (gesture.moveY < 200) {
          ball.x.setValue(gesture.dx);
          ball.y.setValue(gesture.dy);
        }
      },
      onPanResponderRelease: () => {
        ball.flattenOffset();
        if (ball.y._value > 160) {
          ball.y.setValue(160);
        }
        if (ball.y._value < 0) {
          ball.y.setValue(0);
        }
        ball.flattenOffset();
        if (ball.x._value > phoneWidth - 50) {
          ball.x.setValue(phoneWidth - 50);
        }
        if (ball.x._value < 0) {
          ball.x.setValue(0);
        }
      },
    })
  )[0];

  const ball2 = useState(new Animated.ValueXY())[0];
  const panResponder2 = useState(
    new PanResponder.create({
      onStartShouldSetPanResponder: () => false,
      onMoveShouldSetPanResponder: () => true,
      onPanResponderGrant: () => {
        ball2.setOffset({
          x: ball2.x._value,
          y: ball2.y._value,
        });
      },
      onPanResponderMove: (_, gesture) => {
        ball2.x.setValue(gesture.dx);
        ball2.y.setValue(gesture.dy);
      },
      onPanResponderRelease: () => {
        ball2.flattenOffset();
      },
    })
  )[0];

  return (
    <View style={styles.container}>
      <View style={styles.whitefield}>
        <Animated.View
          style={[styles.grayBall, ball.getLayout()]}
          {...panResponder.panHandlers}
        />
      </View>
      <View style={styles.bluefield}>
        <Animated.View
          style={[styles.blueball, ball2.getLayout()]}
          {...panResponder2.panHandlers}
        />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  whitefield: {
    position: "absolute",
    top: 0,
    left: 0,
    height: 200,
    width: 400,
    backgroundColor: "white",
  },
  bluefield: {
    position: "absolute",
    top: Dimensions.get("window").height - 200,
    left: 0,
    height: 200,
    width: 400,
    backgroundColor: "lightskyblue",
  },
  container: {
    flex: 1,
    backgroundColor: "yellow",
    alignItems: "center",
    justifyContent: "center",
  },
  blueball: {
    width: 50,
    height: 50,
    backgroundColor: "blue",
  },
  grayBall: {
    width: 50,
    height: 50,
    backgroundColor: "grey",
  },
});

标签: react-nativeandroid-animationtouch-eventpanresponder

解决方案


这不是一个完整的答案,但作为评论已经太多了:

我不知道如何使视图的平移处理程序不冒泡;(因为我无法阻止处理程序从第二次触摸(即来自不同的视图)运行。我想我将尝试创建自己的版本dx, dy, dx2, dy2 来自被调用的处理程序。大技巧将尝试使用event.nativeEvent.touches哪个是从 in 调用的屏幕上的活动触摸数组onPanResponderMove

onPanResponderMove: Animated.event(
        [
            null,
            { dx: this.pan2.x, dy: this.pan2.y }
        ],
        {
            useNativeDriver: false,
            listener: (event, gestureState) => {

                let touches = event.nativeEvent.touches;
                //do stuff here
            }
        }
)

推荐阅读