将本机平面列表初始滚动到底部

yoo*_*uri 8 chat react-native react-native-flatlist

我正在尝试使用一个在React native中创建聊天 <Flastlist />

像whatsapp和其他聊天应用程序一样,消息从底部开始。

从我的API获取消息后,我调用

this.myFlatList.scrollToEnd({animated: false});
Run Code Online (Sandbox Code Playgroud)

但是它滚动到中间的某个位置,有时滚动到底部的内容较少,有时却什么也不做。

最初如何滚动到底部?

我的聊天消息具有不同的高度,所以我无法计算高度。

小智 25

我用倒置属性和反向函数解决了这个问题

https://facebook.github.io/react-native/docs/flatlist#inverted

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse

<FlatList
   inverted
   data={[...data].reverse()}
   renderItem={renderItem}
   keyExtractor={(item) => item.id}
/>
Run Code Online (Sandbox Code Playgroud)

您可以在聊天组件中使用此解决方案。


小智 17

我有类似的问题。如果你想让你的聊天消息从底部开始,你可以将“inverted”设置为 true 并以相反的方向显示你的消息和时间标签。

在此处检查 FlatList 的“反转”属性。https://facebook.github.io/react-native/docs/flatlist#inverted

如果你想让你的聊天消息从顶部开始,这就是我想要实现的。我在 FlatList 中找不到解决方案,因为正如您所说,高度不同,我无法使用 getItemLayout 使“scrollToEnd”以一种奇怪的方式表现。

我遵循@My Mai 提到的方法,使用 ScrollView 并在 setTimeout 函数中执行 scrollToEnd({animated: false}) 。此外,我添加了一个状态来隐藏内容,直到 scrollToEnd 完成,所以用户不会看到任何滚动。

  • 我使用了您的反向解决方案并将弯曲方向更改为 **column-reverse**。现在它按预期工作:`&lt;FlatList data={messages} inverted contentContainerStyle={{ flexDirection: 'column-reverse' }} /&gt;` (4认同)

per*_*lmq 7

设置initialScrollIndex为您的数据集的长度 - 1。

IE

<Flatlist
data={dataSet}
initialScrollIndex={dataSet.length - 1}
/>
Run Code Online (Sandbox Code Playgroud)

  • 出现异常错误:“scrollToIndex 应与 getItemLayout 或 onScrollToIndexFailed 结合使用” (10认同)

Fre*_*sar 6

截至 2021 年,有两种“好的”解决方案。第一种是超时、引用和 useEffect。这是使用功能组件和 Typescript 的完整示例:

   // Set the height of every item of the list, to improve perfomance and later use in the getItemLayout
   const ITEM_HEIGHT = 100;

   // Data that will be displayed in the FlatList
   const [data, setData] = React.useState<DataType>();

   // The variable that will hold the reference of the FlatList
   const flatListRef = React.useRef<FlatList>(null);

   // The effect that will always run whenever there's a change to the data
   React.useLayoutEffect(() => {
    const timeout = setTimeout(() => {
      if (flatListRef.current && data && data.length > 0) {
        flatListRef.current.scrollToEnd({ animated: true });
      }
    }, 1000);

    return () => {
      clearTimeout(timeout);
    };

   }, [data]);

   // Your FlatList component that will receive ref, data and other properties as needed, you also have to use getItemLayout
   <FlatList
     data={data}
     ref={flatListRef}
     getItemLayout={(data, index) => {
              return { length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index };
     }}
     { ...otherProperties } 
   />

Run Code Online (Sandbox Code Playgroud)

通过上面的示例,您可以有一个流畅的动画滚动到底部。例如,推荐在您收到新消息并且必须滚动到底部时使用。

除此之外,第二种更简单的方法是实现initialScrollIndex将立即加载底部列表的属性,就像您提到的聊天应用程序一样。第一次打开聊天屏幕时效果很好。

像这样:

   // No need to use useEffect, timeout and references... 
   // Just use getItemLayout and initialScrollIndex.

   // Set the height of every item of the list, to improve perfomance and later use in the getItemLayout
   const ITEM_HEIGHT = 100;

   <FlatList
     data={data}
     getItemLayout={(data, index) => {
       return { length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index }; 
     }}
     { ...otherProperties } 
   />

Run Code Online (Sandbox Code Playgroud)


小智 5

我和你遇到了同样的问题,然后我转而使用 ScrollView。它是固定的:

componentDidMount() {
  setTimeout(() => {
    this.scrollView.scrollToEnd();
  });
}

<ScrollView ref={(ref) => { this.scrollView = ref; }} style={styles.messages}>
      {
        messages.map((item, i) => (
          <Message 
            key={i} 
            direction={item.userType === 'banker' ? 'right' : 'left'} 
            text={item.message} 
            name={item.name}
            time={item.createdAt}
          />
        ))
      }
    </ScrollView>`
Run Code Online (Sandbox Code Playgroud)