1

This is a React Native Question.

What I want to achieve is to prevent triggering the scroll event if user is dragging a particular part of a scrollView.

Minimal example:

<View style={{ width: '100%', flex: 1 }}>
    <ScrollView>
        <View style={{ width: '100%', height: 1600, backgroundColor: 'red' }}>
            <View style={{ width: '100%', height: 600, backgroundColor: 'blue' }}/>
        </View>
    </ScrollView
</View>

How can I disable the drag detection (scrolling parent scrollView) of the at the blue part?

Andus
  • 1,713
  • 13
  • 30

2 Answers2

3

You can do a trick solution using onTouchStart and onTouchEnd events inside ScrollView.

Here is the code you can use,

constructor(props) {

            super(props);

            this.state = {
                enabled: true
            };
        }

        render() {

            return (

                <View style={{ width: '100%', flex: 1 }}>
                    <ScrollView
                        scrollEnabled={this.state.enabled}
                        onTouchStart={(event) => {
                            if (event.nativeEvent.locationY < 600) this.setState({ enabled: false });

                        }}
                        onTouchEnd={(event) => {
                            this.setState({ enabled: true });
                        }}
                        >
                        <View style={{ width: '100%', height: 1600, backgroundColor: 'red' }}>
                            <View style={{ width: '100%', height: 600, backgroundColor: 'blue' }}/>
                        </View>
                    </ScrollView>
                </View>

            );

        }

This code only handles scrollEnabled according to your touch position on screen. If you start touching in blue area then it should block scrolling and once you release your finger then it should removes the blocking.

firats
  • 496
  • 2
  • 7
  • Thanks for the quick reply, however, I'm getting some weird values when I look at `event.nativeEvent.locationY`. Like when I randomly click the area that looks like at the same `y`, it comes up with a huge range of variation from very small value like `3` to larger values like `40`... – Andus Aug 07 '19 at 08:25
  • However, in this minimal example, your code is working as expected. I guess it is due to children located in the blue area (not included in the minimal example). Thanks anyways. – Andus Aug 07 '19 at 08:34
  • it is normal. You wanted to not drag if user touches the `blue` part of screen? The area of the blue zone extends from 0 to 600 at the `y` coordinate. This is why we looked the `y` coordinate and range it to between 0 and 600. – firats Aug 07 '19 at 08:38
  • In real life example, I am having a flat list in the blue part, which the blue part is also 600px in height, however, when I press the area in the blue part the `event.nativeEvent.locationY` is giving me weird values. – Andus Aug 07 '19 at 08:40
  • Now it makes sense. In your real code flatlist has its own scroll. When i was trying to answering your question i was thinking there is no other scrollview in that area. Hope it gives you a little idea for your real project. @Andus – firats Aug 07 '19 at 08:44
  • I'm approving your answer based on the minimal example :) – Andus Aug 07 '19 at 08:46
  • But I won't understand, even if the `FlatList` has its own scroll, the clicked area belongs to the `Scrollview` and it should reflect the correct `event.nativeEvent.locationY` value. Do you have anyway to get the correct `event.nativeEvent.locationY` if there's a `FlatList` on the blue area? – Andus Aug 07 '19 at 08:47
  • Yeah the results are weird. I will try and inform you if i find what really causes this situation of yours. – firats Aug 07 '19 at 08:51
  • It is clear that `event.nativeEvent.locationY` shows us coordinate of only selected(clicked) row of flatlist. It sees row as a parent view for itself i think. You also can use `event.nativeEvent.pageY`. It always shows coordinate of page regardless of parent. @Andus – firats Aug 07 '19 at 09:00
  • `pageY` of the blue part will change if the `red` part is scrolled, doesn't looks like a solution, but thanks for the effort – Andus Aug 07 '19 at 09:11
  • this also causes to onPress in a single press. if the user presses the second time, the touch is registered. What could be the root cause for that? – Aditya Kumar Mar 27 '21 at 04:59
0

You can use a TouchableWithoutFeedback component to wrap your blue area and use its onPressIn event as a trigger to disable scrolling of the ScrollView. Use the onTouchEnd event on the ScrollView to enable scrollability again.

export default function MyComponent() {
  const [scrollEnabled, setScrollEnabled] = useState(true);
  return (
    <ScrollView scrollEnabled={scrollEnabled} onTouchEnd={() => { setScrollEnabled(true); }}>
      <View style={{ width: '100%', height: 1600, backgroundColor: 'red' }}>
        <TouchableWithoutFeedback onPressIn={() => { setScrollEnabled(false); }}>
          <View style={{ width: '100%', height: 600, backgroundColor: 'blue' }}/>
        </TouchableWithoutFeedback>
      </View>
    </ScrollView
  );
};
Marinne
  • 331
  • 3
  • 5