3

I am developing an app with react native. I have this UI element which is similar to that of Maps in iOS, in which you slide a panel from the bottom and inside it, there is a scrollable list.

For the slide-out panel, I am using a component called rn-sliding-up-panel. It has several props as event listeners. For example

<SlidingUpPanel
  allowDragging={/*Boolean*/}
  onDragStart={()=>{}   /*When it is about to be dragged*/}
  onDrag={()=>{} /*When it is being dragged*/}
  onDragEnd={()={} /*When the user is no longer touching the screen*/}
></SlidingUpPanel>

Inside it, I have a <ScrollView> containing a <List> from react-native-elements. As far as I know, it has only one vent listener, being:

<ScrollView onScroll={()=>{}}></ScrollView>

My issue is that scrolling on the list actually causes the panel to close (it closes by sliding down). I found a work-around by adding a state, and modfiying it onScroll:

state = {
  dragPanel: true,
}
/*===========================================*/
<SlidingUpPanel allowDragging={this.state.dragPanel}>
     <ScrollView onScroll={()={ this.setState({dragPanel: false}) }}></ScrollView>
</SlidingUpPanel>

However, I cannot find a way to restore the dragging, and it doesn't fire up as efficiently.


TL;DR

Is there an eficient way to implement a ScrollView inside a SlidingUpPanel without the events of each overlapping? Maybe using something similar to function(e){e.preventDefault();}?

Val
  • 21,938
  • 10
  • 68
  • 86
edvilme
  • 570
  • 7
  • 16

3 Answers3

5

To properly disable / restore outer scroll dragging, do

_onGrant() {
  this.setState({ dragPanel: false });
  return true;
}

_onRelease() {
  this.setState({ dragPanel: true });
}

constructor(props) {
  super(props);

  this._onGrant = this._onGrant.bind(this);
  this._onRelease = this._onRelease.bind(this);

  this._panResponder = PanResponder.create({
    onMoveShouldSetPanResponder: this._onGrant,
    onPanResponderRelease: this._onRelease,
    onPanResponderTerminate: this._onRelease,
  });
}

render() {
  <SlidingUpPanel allowDragging={this.state.dragPanel}>
    <ScrollView
      {...this._panResponder.panHandlers}
    />
  </SlidingUpPanel>
}

From what I had been searching for a long time, preventDefault() is a pure web-javascript thing, I think there are no preventDefault in react-native.

From document section Handling Touches, react-native just use javascript to simulate Objc (iOS) & Java (Android) events.

Val
  • 21,938
  • 10
  • 68
  • 86
  • Thanks for answering. From what I understand, `_onGrant()` should be fired when the user starts scrolling, and `_onRelease()` when the user stops scrolling. And `this._panResponder` fires them up accordingly. However, how should I implement it into the ``?? (That is, no property name or anything?) – edvilme Dec 13 '17 at 02:26
  • @edvilme `{...this._panResponder.panHandlers}` does exactly what you describe. that called *transferring props* https://zhenyong.github.io/react/docs/transferring-props.html – Val Dec 13 '17 at 02:33
  • Thank you. Unfortunately, this doesn't seem to solve the issue. It helped me though,I added an event listener to a handle and rejected dragging in all the scroll events. Thank you!!! – edvilme Dec 13 '17 at 04:47
  • This worked for me. Thank you! However if there are any child views inside the ScrollView, they need the same PanResponder added to them as well. I also had to add the onGrant method to the PanResponders onStartShouldSetPanResponder function otherwise it was flaky. – Dylan Vester Mar 31 '18 at 17:36
0

Set the minimumDistanceThreshold property to something around 50. Maybe 30 for small screens and 50-60 for bigger ones. Do it like so:

<SlidingUpPanel minimumDistanceThreshold={isSmallScreen ? 30 : 50}>
  <ScrollView style={{flex: 1}}>
  </ScrollView> 
</SlidingUpPanel>
spatak
  • 1,039
  • 1
  • 14
  • 25
-1

It might be late for an answer but use your scroll view as absolute positioned and position it accordingly.

Think of the scroll view as a pop-up dialog that appears in front of the backdrop behind it. Upon clicking the backdrop, the pop-up dismisses. Apply similar logic to the issue by letting scroll view in front of the slide up panel.

Alish Giri
  • 1,855
  • 18
  • 21