Подтвердить что ты не робот

Можно ли прокручивать ScrollView до конца?

Для приложения, подобного чату, я хочу, чтобы компонент ScrollView прокручивался снизу, потому что самые новые сообщения появляются под более старыми. Можем ли мы отрегулировать положение прокрутки ScrollView?

4b9b3361

Ответ 1

Для React Native 0.41 и более поздних scrollToEnd вы можете сделать это со встроенным методом scrollToEnd:

<ScrollView
    ref={ref => this.scrollView = ref}
    onContentSizeChange={(contentWidth, contentHeight)=>{        
        this.scrollView.scrollToEnd({animated: true});
    }}>
</ScrollView>

Ответ 2

Используйте onContentSizeChange, чтобы отслеживать нижний Y прокрутки (высота)

https://facebook.github.io/react-native/docs/scrollview.html#oncontentsizechange

var _scrollToBottomY

<ScrollView
    onContentSizeChange={(contentWidth, contentHeight)=>{
    _scrollToBottomY = contentHeight;
    }}>
</ScrollView>

затем используйте имя ссылки вида прокрутки, как

this.refs.scrollView.scrollTo(_scrollToBottomY);

Ответ 3

Вот самое простое решение, которое я мог бы собрать:

 <ListView
ref={ref => (this.listView = ref)}
onLayout={event => {
    this.listViewHeight = event.nativeEvent.layout.height;
}}
onContentSizeChange={() => {
    this.listView.scrollTo({
        y: this.listView.getMetrics().contentLength - this.listViewHeight
    });
}}
/>;

Ответ 4

попробуйте это решение

xcode 10.0

RN: 56,0,0

<ScrollView ref="scrollView"
             onContentSizeChange={(width,height) => this.refs.scrollView.scrollTo({y:height})}>  </ScrollView> // OR height -  width

Ответ 5

Вы можете инвертировать представление прокрутки/списка с помощью модуля react-native-invertible-scroll-view, а затем просто вызвать ref.scrollTo(0) для прокрутки вниз.

Установите модуль:

npm install --save react-native-invertible-scroll-view

Затем импортируйте компонент:

import InvertibleScrollView from 'react-native-invertible-scroll-view';

Затем используйте следующий JSX вместо ScrollView:

<InvertibleScrollView inverted
    ref={ref => { this.scrollView = ref; }}
    onContentSizeChange={() => {
        this.scrollView.scrollTo({y: 0, animated: true});
    }}
>
    { /* content */ }
</InvertibleScrollView>

Это работает, потому что react-native-invertible-scroll-view обратной связью с обратной связью с обратной связью переворачивает весь контент представления. Обратите внимание, что дети с представлением также будут отображаться в обратном порядке к нормальному виду - первый ребенок появится внизу.

Ответ 6

Этот метод немного взломан, но я не смог найти лучший способ

  • Сначала добавьте ссылку на свой ScrollView.
  • Второе добавьте фиктивный вид перед закрытием тега ScrollView
  • Получить позицию y этого макета.
  • Всякий раз, когда вы хотите прокрутить вниз, прокрутите до положения макета.

var footerY; //Y position of the dummy view
render() {    
    return (
      <View>
          <ScrollView 
          ref='_scrollView'>
            // This is where all the things that you want to display in the scroll view goes
            
            // Below is the dummy View
            <View onLayout={(e)=> {
              footerY = e.nativeEvent.layout.y;
              }}/>
          </ScrollView>
              
          //Below is the button to scroll to the bottom    
          <TouchableHighlight
            onPress={() => { this.refs._scrollView.scrollTo(footerY); }}>
            <Text>Scroll to Bottom</Text>
          </TouchableHighlight>
        
      </View>
    );
  }

Ответ 7

Это отвечает на ваш вопрос: fooobar.com/questions/133894/...

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

Ответ 8

Возможно, это поможет кому-то с подобными проблемами при работе с элементами в списке.

Это позволит прокрутить до предыдущего элемента в списке. Я использую его в приложении для обмена сообщениями.

<FlatList
    data={data.messages}
    ref={ref => this.scrollView = ref}
    onContentSizeChange={(contentWidth, contentHeight)=>{
        this.scrollView.scrollToIndex({index: data.messages.length - 2});
    }}
    renderItem={({item}) => this.renderItem(item)}
/>

Ответ 9

Некоторое время я боролся с этим и, наконец, придумал что-то, что сработало очень хорошо и гладко для меня. Как и многие, я пытался .scrollToEnd безрезультатно. Решение, которое сработало для меня, заключалось в комбинации onContentSizeChange, onLayout реквизита и немного большего визуального осмысления того, "что в действительности означает прокрутка до дна". Последняя часть кажется мне тривиальной, но мне потребовалось вечно, чтобы понять.

Учитывая, что ScrollView имеет фиксированную высоту, когда высота содержимого превышает высоту контейнера, я рассчитал смещение, вычтя prevHeight (фиксированная высота ScrollView) для currHeight (высота содержимого), Если вы можете визуально представить это, прокрутив эту разницу по оси Y, сдвиньте высоту содержимого над своим контейнером на это смещение. Я увеличил свое смещение и сделал текущую высоту содержимого моей предыдущей высотой и продолжал вычислять новое смещение.

Вот код Надеюсь, это кому-нибудь поможет.

class ChatRoomCorrespondence extends PureComponent {
  currHeight = 0;
  prevHeight = 0;
  scrollHeight = 0;

  scrollToBottom = () => {
    this.refs.scrollView.getScrollResponder().scrollResponderScrollTo({
      x: 0,
      y: this.scrollHeight,
      animated: true
    });
  };

  render() {
    return (
      <ScrollView
        style={Styles.container}
        ref="scrollView"
        onContentSizeChange={(w, h) => {
          this.currHeight = h;

          if (
            this.prevHeight > 0 &&
            this.currHeight - this.scrollHeight > this.prevHeight
          ) {
            this.scrollHeight += this.currHeight - this.prevHeight;
            console.log("--------------------------------------------");
            console.log("Curr: ", this.currHeight);
            console.log("Prev: ", this.prevHeight);
            console.log("Scroll: ", this.scrollHeight);
            this.prevHeight = this.currHeight;
            console.log("PREV: ", this.prevHeight);
            console.log("--------------------------------------------");

            this.scrollToBottom();
          }
        }}
        onLayout={ev => {
          // Fires once
          const fixedContentHeight = ev.nativeEvent.layout.height;
          this.prevHeight = fixedContentHeight;
        }}
      >
        <FlatList
          data={this.props.messages}
          renderItem={({ item }) => (
            <ChatMessage
              text={item.text}
              sender={item.sender}
              time={item.time}
              username={this.props.username}
            />
          )}
          keyExtractor={(item, index) => index.toString()}
        />
      </ScrollView>
    );
  }
}

Ответ 10

Я думаю, что уже слишком поздно, чтобы ответить, но я получил один взлом! Если вы используете FlatList, вы можете активировать свойство inverted, которое возвращается к установке transform scale на -1 (что приемлемо для других компонентов списка, таких как ScrollView...). Когда вы визуализируете свой FlatList с данными, он всегда будет внизу!

Ответ 11

Попробуйте установить свойство contentOffset прокрутки в соответствии с текущей высотой содержимого.

Чтобы выполнить то, что вам нужно, вы можете сделать это как часть события onScroll. Однако это может привести к плохому пользовательскому опыту, поэтому может оказаться более удобным для пользователя, если это произойдет только при добавлении нового сообщения.

Ответ 12

У меня была аналогичная проблема, но после прочтения этой страницы (которая дает мне головную боль!) я нахожу этот очень приятный пакет npm, который просто инвертируйте ListView и упростите приложение чата!