是否可以将ScrollView滚动到底部?

时间:2015-03-27 21:32:48

标签: react-native

对于类似聊天的应用,我希望将ScrollView组件滚动到底部,因为最新的消息会显示在较旧的消息下。我们可以调整ScrollView的滚动位置吗?

17 个答案:

答案 0 :(得分:113)

对于 React Native 0.41及更高版本,您可以使用内置的scrollToEnd方法执行此操作:

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

答案 1 :(得分:24)

使用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);

答案 2 :(得分:18)

这是我可以采用的最简单的解决方案:

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

答案 3 :(得分:13)

对于任何编写可以使用钩子的功能组件的人,

import React, { useRef } from 'react';
import { ScrollView } from 'react-native';

const ScreenComponent = (props) => {
  const scrollViewRef = useRef();
  return (
    <ScrollView
      ref={scrollViewRef}
      onContentSizeChange={() => scrollViewRef.current.scrollToEnd({ animated: true })}
    />
  );
};

答案 4 :(得分:5)

如果有人在2020年或更晚的时候想知道如何使用功能组件来实现这一目标。这是我的做法:

ref={ref => scrollView = ref }
onContentSizeChange={() => scrollView.scrollToEnd({ animated: true })}>

答案 5 :(得分:3)

您可以使用react-native-invertible-scroll-view module反转滚动/列表视图,然后只需拨打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 :(得分:2)

尝试此解决方案

xcode 10.0

RN:56.0.0

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

答案 7 :(得分:1)

这种方法有点乱,但我找不到更好的方法

  1. 首先在您的ScrollView中添加一个引用。
  2. 在关闭ScrollView标记之前添加虚拟视图
  3. 获取虚拟视图的y位置
  4. 每当您想要滚动到底部滚动到虚拟视图的位置
  5. 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>
        );
      }

答案 8 :(得分:0)

这回答了你的问题: https://stackoverflow.com/a/39563100/1917250

您需要通过计算内容的高度减去其scrollView的高度来不断滚动到页面底部。

答案 9 :(得分:0)

在处理列表中的项目时,这可能有助于遇到类似问题的人。

这将滚动到列表中的上一个项目。我在消息应用程序中使用它。

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

答案 10 :(得分:0)

我为此奋斗了一段时间,最后想出了对我来说非常有效和流畅的东西。像许多人一样,我尝试.scrollToEnd无济于事。对我有用的解决方案是onContentSizeChangeonLayout个道具的组合,再加上一些视觉上的思考,即“滚动到底”是什么意思。现在对我而言,最后一部分似乎微不足道,但我花了很长时间才弄清楚。

鉴于ScrollView的高度是固定的,当内容高度超过容器的高度时,我通过减去prevHeightScrollView的固定高度)来计算偏移量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>
    );
  }
}

答案 11 :(得分:0)

我想现在回答还为时已晚,但是我得到了一个破解!如果您使用FlatList,则可以启用inverted属性,该属性可退回到将transform scale设置为-1(其他列表组件,例如ScrollView可以接受... )。当您使用数据渲染FlatList时,它总是位于底部!

答案 12 :(得分:0)

@Aniruddha答案实际上对我不起作用,因为我使用的是"react-native": "0.59.8",而this.scrollView.root.scrollToEnd也是未定义的

但是我发现了这一点,this.scrollView.scrollResponderScrollToEnd({animated: true});

如果您使用的是0.59.8,则可以使用;如果您使用的是更高版本,则可以使用。请在此答案中添加版本,以免其他人遇到麻烦。

完整代码在这里

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

答案 13 :(得分:0)

如果您使用TypeScript,则需要执行此操作

interface Props extends TextInputProps { 
     scrollRef?: any;
}

export class Input extends React.Component<Props, any> {
     scrollRef;
constructor(props) {
    this.scrollRef = React.createRef();
}
<ScrollView
    ref={ref => (this.scrollRef = ref)}
    onContentSizeChange={() => {
    this.scrollRef.scrollToEnd();
    }}
>
</ScrollView>

答案 14 :(得分:-1)

我遇到了类似的问题,但是在看完这个页面后(让我头疼!)我发现this very nice npm package只是反转了ListView,让聊天应用程序变得简单!

答案 15 :(得分:-1)

尝试将滚动视图的contentOffset属性设置为内容的当前高度。

要完成您的需要,您可以在onScroll事件中执行此操作。然而,这可能会导致糟糕的用户体验,因此只有在附加新消息时才能实现此目的,这可能更加用户友好。

答案 16 :(得分:-3)

有点晚......但看看这个问题。 Scroll to top of ScrollView

ScrollView有一个“scrollTo”方法。