简体   繁体   中英

why ScrollView inside Animated.View not working?

i want to ask question here, i 've made draggable view using pan responder. i managed it to only move up and down. here is my pan responder config

this.panResponder = PanResponder.create({
  onStartShouldSetPanResponder: (event, gesture) => true,
  // THIS TRACK MOVEMENT OF OUR FINGER 
  onPanResponderMove: (event, gesture) => {
    if (gesture.dy > 0) {
      this.position.setValue({ y: gesture.dy });
    }
  },
  onPanResponderRelease: (event, gesture) => {
    if (gesture.dy > SWIPE_THRESHOLD) {
      this.forceSwipeDown();
    } else {
       this.resetPosition();
    }
  },
});

i use it in animated.view, here is the code

<Animated.View
       style={[modalCard, this.position.getLayout()]}
       {...this.panResponder.panHandlers}
      >
        {
          // XButton
        }
        <TouchableOpacity style={button} onPress={() => this.props.closeModal()}>
          <Icon 
            name='times'
            size={wp(20)}
            color='#A9A9A9'
          />
        </TouchableOpacity>
        <View style={topBorders}>
          <View style={doubeLine} />
        </View>
        {this.props.children}
      </Animated.View>

my question is, when i put ScrollView as children of this component, the scrollview wont scroll. i dont know why is it behave like this, thank you.

On the ScrollView , there is a default JS pan responder. Here, you create the PanResponder in the Animated.View . In the negotiations process, Animated.View become the responder of the touches, while the ScrollView not.

Solution:

You can capture the touch events outside the ScrollView while ignore the touch events inside the ScrollView . By doing this, the ScrollView can scroll.

The code may like this:

    _ignoreRegion = {
      x: 0,
      y: 0,
      width: 0,
      height: 0
    }


    _onLayout = ({
      nativeEvent: {
        layout: {
          x,
          y,
          width,
          height
        }
      }
    }) => {
      this._ignoreRegion = nativeEvent.layout;
    };

    _isInsideRegion = (x, y, region) => {
       return x >= region.x && x <= region.x + region.width && y >= region.y && y <= region.y + region.height;
    }

    this._panResponder = PanResponder.create({
        onMoveShouldSetPanResponderCapture: (evt, gestureState) => {
           if (this._isInsideRegion(evt.pageX, evt.pageY, this._ignoreRegion)) {
             return false; 
           } else {
             return true; 
           }
        },
        // .... 
    })

The JSX

 <Animated.View {...this._panResponder.panHandlers}>            
    <ScrollView onLayout={this._onLayout}/>
</Animated.View> 

I was able to include a ScrollView inside Animated.View by configuring when onMoveShouldSetPanResponder (NOT onMoveShouldSetPanResponderCapture as suggested by another answer ) should return true. When it returns true, Animated.View will capture the sliding event. When it returns false, the sliding event is ignored by Animated.View and captured by whatever view is underneath. Thus, say we know the x-coord range of the ScrollView is [xLo, xHi] and the y-coord range is [yLo, yHi] , we can create a panResponder as such

const panResponder = React.useRef(
  PanResponder.create({
    onMoveShouldSetPanResponder: (_, {dx, dy, moveX, moveY}) => {
      if (xLo <= moveX && moveX <= xHi && yLo <= moveY && moveY <= yHi) {
        return false;
      }
      return true;
  }),
).current;

This panResponder guarantees that Animated.View ignores all sliding event within the boundary set by [xLo, xHi] and [yLo, yHi] , but registers sliding events outside the boundary.

[xLo, xHi] and [yLo, yHi] can be obtained by the measure callback.

Below is a demo implemented using this method. For more demos and source code, check the documentation .

Full disclosure, I am the author of @fanchenbao/react-native-sliding-drawer .

在此处输入图像描述

I am using like this, and it's working on my project:

<Animated.View>
    <ScrollView>
        { this.renderMultimpleItems() }
    </ScrollView>
</Animated.View>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM