Реагировать на родной ScrollView отключить одно направление при условии

Можно ли прокрутить только в одном направлении? У меня есть функция, которая определяет направление прокрутки пользователя.

Но я не могу понять, как я могу установить флаг, что, если пользователь не ответит на вопрос, он не позволит ему прокрутить вправо только влево?

благодарю вас

4 ответа

Я создал небольшой пример, где разрешена только прокрутка вправо. Конечно, этот пример можно адаптировать, чтобы разрешить левую прокрутку в определенных условиях. В коде я обозначил позицию, где добавить такое условие.

демонстрация

объяснение

Пример состоит из двух основных частей.

  1. Определение направления прокрутки и отключение прокрутки при необходимости
  2. Включение прокрутки снова

Определение направления прокрутки

См комментарии кода для объяснения

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 });
      }
    }

Включение прокрутки снова:

Мы используем таймер, чтобы снова включить прокрутку через определенное время.

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});
  }
}

Рендер:

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

Рабочий пример

https://snack.expo.io/rJAamRC2E

Ты можешь использовать react-native-directed-scrollview пакет

Пакет: https://www.npmjs.com/package/react-native-directed-scrollview

Этот пакет имеет scrollTo({x: 100, y: 100, animated: true}) метод. если вы ограничите координаты оси X вашими условиями, все будет в порядке.

Так что попробуйте что-то вроде этого,

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

примечание: вы можете пройти false в animated параметр. Это необязательно.

Если вы использовали default-native по умолчанию scrollview Вы включаете или отключаете это легко

<ScrollView 
     scrollEnabled ={this.state.shouldScorll}
>
...
</ScrollView>

но я не думаю, что есть возможность установить направление, чтобы идти вниз по вертикали всегда

Для тех, кто хочет контейнер фиксированной высоты со скрытым содержимым, но нуждается в RefreshControlфункциональность, то, что я сделал, было использовано ScrollViewно фиксированная его высота.

Когда я хочу показать другой контент, я анимирую высоту/непрозрачность каждого блока контента, чтобы создать эффект прокрутки.

      <ScrollView
    refreshControl={...}
    style={{ height: contentBlockHeight, overflow: 'hidden' }}
    contentContainerStyle={{ height: contentBlockHeight, overflow: 'hidden' }}
>
...
</ScrollView>
Другие вопросы по тегам