React native ScrollView disable one direction on condition
Asked Answered
S

3

15

is it possible to scroll only to one direction? I have a function that detects the direction the user is a scroll.

But I can't figure out how can I set a flag, that if the user doesn't answer the question it will not allow him to scroll right only left?

thank you

Syllogism answered 29/3, 2018 at 6:18 Comment(1)
directionalLockEnabled - Will this be useful for you? facebook.github.io/react-native/docs/… - Only on iOSCircumgyration
M
3

I have created a small example, where only scrolling to the right is allowed. Of course this example can be adapted to allow left scrolling in specific conditions. In the code, I marked the position where to add such a condition.

Demo

enter image description here

Explanation

The example consists of two main parts.

  1. Detecting the scroll direction and disable scroll if necessary
  2. Enabling the scroll again

Detecting scroll direction

See code comments for explanation

handleScroll(event){
      // WIDTH originates from Dimensions.get('screen').width
      const endOfView = event.nativeEvent.contentSize.width - WIDTH; 
      const positionX = event.nativeEvent.contentOffset.x; 
      const positionY = event.nativeEvent.contentOffset.y; 

      // check if we are scrolling left, also detect if we are at the end of the scrollview 
      // MARKED: check other conditions here to allow scrolling again
      if(this.state.lastPositionX > positionX && endOfView > positionX){
        // we are scrolling left, disable scroll, reset the current position
        this.setState({ lastPositionX: positionX, lastPositionY: positionY, allowScroll: false });
        // scroll back to last valid position. Important! Otherwise users may be able to scroll left
        this._scrollview.scrollTo({x: this.state.lastPositionX, y: this.state.lastPositionY});
        //call the timer to enable scroll again 
        this.callTimer();
      }else{
        // we are scrolling right, everthing is fine
        this.setState({ lastPositionX: positionX, lastPositionY: positionY });
      }
    }

Enabling scroll again:

We are making use of a timer to enable scroll again after a specified amount of time.

timerFn() {
  // clear the timer again, otherwise the timer will fire over and over again 
  clearInterval(this.state.timer);
  //enable scroll and reset timer 
  this.setState({allowScroll: true, timer: null });

}
callTimer() {
  if (this.state.timer == null ){ 
    // no timer is available, we create a new one. Maybe you have to fine tune the duration 
    let timer = setInterval(() => this.timerFn(), 1000);
    this.setState({timer});
  }
}

Render:

  <SafeAreaView style={styles.container}>
   <ScrollView
   horizontal
   scrollEventThrottle={15}
   scrollEnabled={this.state.allowScroll}
   onScroll={(event) => this.handleScroll(event)}
   ref={view => this._scrollview = view}
   >
     <View style={{width: WIDTH, backgroundColor: 'red'}} />
     <View style={{width: WIDTH, backgroundColor: 'green'}} />
     <View style={{width: WIDTH, backgroundColor: 'blue'}} />
   </ScrollView>
  </SafeAreaView>

Working Example

https://snack.expo.io/rJAamRC2E

Moria answered 19/5, 2019 at 13:20 Comment(0)
M
1

You can use react-native-directed-scrollview package

Package: https://www.npmjs.com/package/react-native-directed-scrollview

This package has scrollTo({x: 100, y: 100, animated: true}) method. if you restrict x-axis coordinate to your conditions, it will be ok.

So try something like this,

if(isAnswered == false){
  scrollTo({x: /*x-axis position*/, y: /*y-axis position*/, animated: true})
}

note: you can pass false to animated parameter. It is optional.

Melcher answered 17/5, 2019 at 10:43 Comment(1)
no need to use an additional package. The scrollTo function is available for the standard ScrollViewMoria
D
0

For anyone who wants a fixed-height container with hidden content but need the RefreshControl functionality of a ScrollView, what i did was used a ScrollView but fixed its height.

When i want to show other content i animate the height/opacity of each content block to give the effect of scrolling.

<ScrollView
    refreshControl={...}
    style={{ height: contentBlockHeight, overflow: 'hidden' }}
    contentContainerStyle={{ height: contentBlockHeight, overflow: 'hidden' }}
>
...
</ScrollView>
Dean answered 4/2, 2022 at 12:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.