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.
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.