Closed lukekarrys closed 9 years ago
I believe, but would need to verify, what is happening is the map view is a child of the drawer, and hence has first dibs at responding to the pan. The event propogates up to the drawer, which then also pans. I am not sure how to solve this elegantly.
I suspect you could put an invisible View as a child as a sibling after the MapView, and set up a pan responder. Since this view will have a "higher" z index, it will get first dibs on the pan responder, and furthermore I suspect it will propogate up to the Drawer without ever triggering the pan on the MapView.
I have not played with the way pan and event propogation works much, so this would definitely take some tinkering to get right. If the above method does work, we could potentially add a new prop preventPanPropogation
Not sure when I will have time to look into this, but please let me know if you get it working!
Thanks for the tips @rt2zz. I'll keep investigating, and if I find an elegant solution that would work within react-native-drawer
I'll submit a PR :smile:
Code for what I had in mind (again not sure if this will work, but I think the approach would look something like this):
const styles = StyleSheet.create({
shadow: {
shadowColor: '#000000',
shadowOpacity: 0.6,
shadowRadius: 15,
flex: 1
},
map: {
flex: 1
},
panCapture: {
width: 20,
height: fullHeight,
position: 'absolute',
left:0,
top:0,
}
});
export default React.createClass({
componentWillMount: function() {
this._panGesture = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {},
onPanResponderMove: (evt, gestureState) => {},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {},
onPanResponderTerminate: (evt, gestureState) => {},
onShouldBlockNativeResponder: (evt, gestureState) => {},
});
},
render () {
return (
<Drawer type='static' content={<Settings {...this.state} />}>
<View style={styles.shadow}>
<MapView style={style.map} {...this.state} />
<View style={style.panCapture} {...this._panResponder.panHandlers} />
</View>
</Drawer>
);
}
});
@lukekarrys I just learned about onStartShouldSetPanResponderCapture
which may be the solution here. I just pushed 1.2.6 with a new captureGestures
prop. Set that to true and you may be able to get something workable for your use case.
Combining the invisible panCapture
view and captureGestures={true}
did the trick! Thanks @rt2zz!
In case anyone else wants to see my full implementation:
import React, {StyleSheet, View, Component, PropTypes, NativeModules} from 'react-native';
import Drawer from 'react-native-drawer';
const screen = NativeModules.UIManager.Dimensions.window;
const styles = StyleSheet.create({
drawer: {
shadowColor: '#000000',
shadowOpacity: 0.6,
shadowRadius: 15,
flex: 1
},
panCapture: {
height: screen.height,
backgroundColor: 'transparent',
position: 'absolute',
left: 0,
top: 0
}
});
export default class CaptureDrawer extends Component {
static propTypes = {
children: PropTypes.node.isRequired,
panOpenMask: PropTypes.number.isRequired
}
render () {
const {children, ...drawerProps} = this.props;
const {panOpenMask} = drawerProps;
const panOpenWidth = screen.width * panOpenMask;
return (
<Drawer {...drawerProps} captureGestures={true}>
<View style={styles.drawer}>
{children}
<View style={[styles.panCapture, {width: panOpenWidth}]} />
</View>
</Drawer>
);
}
}
then from my main view I can render like this:
<CaptureDrawer type='static' panOpenMask={0.1} content={<Settings />}>
<ContentView />
</CaptureDrawer>
nice! I was thinking about making some implementation specific modules like material-drawer
or what have you. This is awesome!
BTW are you sure you still need the panCapture view? I think captureGestures might be sufficient.
@rt2zz You're right! And if you see in the example, the capturePanHandlers
are never even being passed to the View
. They were left over from my previous implementation and I didn't realize I wasn't even using them anymore. :grinning: I'l gonna edit the comment and remove the componentWillMount
method.
good stuff, if only we had known how onStartShouldSetPanResponderCapture
worked from the get go! :)
First off, thanks for this component, it has worked great and the API has been very easy to use. :smile:
I have an app that is a full screen
MapView
with aSettings
view as the drawer. What I'm seeing is that (with what I've tried so far) I can't start panning the drawer without the map also panning for the duration of the drawer panning.I'm not sure if this should (or can) be solved within
react-native-drawer
, but if you have any ideas about what could work, I would greatly appreciate it.Here's the code I'm using currently for my registered component:
Things I've tried:
onPanResponderTerminationRequest: (evt, gestureState) => true
. The docs don't say exactly what this does, but it sounded like the right idea, although it didn't work.PanResponder
.onPanStart
andonPanEnd
methods to the drawer and updatingscrollEnabled
ofMapView
(caused laggy performance or missed pans).