【问题标题】:How can I pass additional data to panResponder (React Native)?如何将其他数据传递给 panResponder (React Native)?
【发布时间】:2020-02-02 10:36:04
【问题描述】:

我正在开发一个项目,其中有多个 <Image /> 组件,但我遇到了一个问题,即我无法在任何给定时间指示用户正在抓取哪个图像。解决此问题的第一个想法是将图像包装在TouchableOpacity 中,onPress 函数将触发并传递图像的数据以更新状态 (this.setState({ currentImage: imageData }))。但这不适用于panResponder。所以我的问题是, 有没有办法将数据传递给 panResponder 或者我怎样才能让 panResponder 用户正在抓取哪个图像?

class App extends React.Component {

  point = new Animated.ValueXY();

  constructor() {
    super();
    this.state = {
      shapesArr: [],
      isGrabbing: false,
      currentShape: {},
    };
this._panResponder = PanResponder.create({
      // Ask to be the responder:
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

      onPanResponderGrant: (evt, gestureState) => {
        console.log(findNodeHandle(evt.nativeEvent.target));
        this.setState({ isGrabbing: true });
        Animated.event([{ x: this.point.x }])({ x: gestureState.x0 - 21 })
        Animated.event([{ y: this.point.y }])({ y: gestureState.y0  - 21})

        // The gesture has started. Show visual feedback so the user knows
        // what is happening!
        // gestureState.d{x,y} will be set to zero now
      },
      onPanResponderMove: (evt, gestureState) => {
        // console.log(gestureState);
        Animated.event([{ y: this.point.y }])({ y: gestureState.moveY - 21 })
        Animated.event([{ x: this.point.x }])({ x: gestureState.moveX - 21 })
        // Animated.event([{ x: this.point.x }])({ x: gestureState.moveX })


        // The most recent move distance is gestureState.move{X,Y}
        // The accumulated gesture distance since becoming responder is
        // gestureState.d{x,y}
      },
      onPanResponderTerminationRequest: (evt, gestureState) => false,
      onPanResponderRelease: (evt, gestureState) => {
        // this.setState({ isGrabbing: false });

        // The user has released all touches while this view is the
        // responder. This typically means a gesture has succeeded
      },
      onPanResponderTerminate: (evt, gestureState) => {
        // this.setState({ isGrabbing: false });

        // Another component has become the responder, so this gesture
        // should be cancelled
      },
      onShouldBlockNativeResponder: (evt, gestureState) => {
        // Returns whether this component should block native components from becoming the JS
        // responder. Returns true by default. Is currently only supported on android.
        return true;
      },
    });
  }

  componentDidMount() {
    this.setState({ shapesArr: getShapes()})
  }

  render() {
    const { shapesArr, isGrabbing } = this.state;

    const renderShape = ( shape, i ) => (
      <Image 
        key={`${shape.name}${i}`} 
        style={style.shapeImg} 
        source={shape.activeImg} 
        {...this._panResponder.panHandlers} 
      >
    )
    return (
      <View style={style.container}>
        {isGrabbing && (
          <Animated.View
            style={[
              { 
                position: 'absolute',
                zIndex: 2, 
                top: this.point.y,
                left: this.point.x,
              }]}
          >
            {renderShape({ id: 2, name: 'star', activeImg: starImg }, 2)}
          </Animated.View> 
        )}
        <View style={style.selectionContainer}>
          {shapesArr.map((shape, i) => renderShape(shape, i))}
        </View>

      </View>
    )
  }
}

【问题讨论】:

    标签: react-native animation drag-and-drop components


    【解决方案1】:

    我能够回答我自己的问题。我如何解决我的问题很简单。我将数据(一个对象)作为道具传递到每个&lt;Image /&gt; 组件中,如下所示:&lt;Image shape={shape} /&gt;。使用 prop 注入组件后,我转到 onPanResponderGrant: (evt, gestureState) 并在 memoizedProps (evt._targetInst.memoizedProps.shape) 中找到。获得要查找的数据后,我会使用它更新状态。

    【讨论】:

      【解决方案2】:

      您可以将图像分割成一个屏幕,并在该屏幕上使用 panResponder 功能。

      【讨论】:

      • 感谢您这么快回复! @Thanh Cao,您能否具体说明一下您的意思,“将图像分割成一个屏幕并在此屏幕上使用 panResponder”?
      • 我的意思是为每个图像使用一个。将每个图像拆分为自己的组件并使用每个 panResponder 函数
      【解决方案3】:
       class ImageCustom extends React.PureComponent{
          constructor(props){
             super(props)
             this._panResponder = PanResponder.create({....})
          }
          render(){
           const {source, style} = this.props
           return(
             <Image source={source} style={style} {...this._panResponder.panHandlers} />
           )     
         }
      }
      

      App.js

      class App extends React.Component {
        const renderShape = ( shape, i ) => (
            <ImageCustom 
              key={`${shape.name}${i}`} 
              style={style.shapeImg} 
              source={shape.activeImg} 
            >
          )
       ...
      }
      

      【讨论】:

      • 谢谢@Thanh Cao,感谢您花时间解释您的答案。我会自己试试。我也确实找到了解决这个问题的不同方法。它不像你的那么优雅,但我会在这里发布它作为答案。一旦我尝试了两者并确定哪个更好(关于性能、可读性和最佳实践)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多