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

问题描述 投票:0回答:15

我正在尝试使用

<Flatlist />

在 React Native 中创建聊天

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

从 API 获取消息后,我调用

this.myFlatList.scrollToEnd({animated: false});

但它会滚动到中间的某个位置,有时底部的项目较少,有时什么也不做。

如何首先滚动到底部?

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

react-native chat react-native-flatlist
15个回答
46
投票

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

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

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

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


20
投票

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

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

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


12
投票

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

<Flatlist
data={dataSet}
initialScrollIndex={dataSet.length - 1}
/>

8
投票

我和你遇到了同样的问题,然后我转而使用 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>`

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

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

除此之外,第二种更简单的方法是实现

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


2
投票

我找到了一个 100% 对我有用的解决方案

将参考文献

flatListRef
添加到我的平面列表中:

<Flatlist
     reference={(ref) => this.flatListRef = ref}
     data={data}
     keyExtractor={keyExtractor}
     renderItem={renderItem}
/>

然后,每当您想自动滚动到列表底部时,请使用:

this.flatListRef._listRef._scrollRef.scrollToEnd({ animating: true });

是的,您应该访问元素 _listRef 然后访问 _scrollRef 然后调用 scrollToEnd 🙄


  • 反应原生0.64.1
  • 反应17.0.2


1
投票

我也一直在努力解决这个问题,并发现对我来说最好的渲染无故障的解决方案是:

  1. 使用
    inverted={-1}
    道具
  2. 在我的例子中,使用reverse() javascript函数使用
    data={MyArrayofMessages.reverse()}
    反转数组中消息对象的顺序。
    
    
  3. 非常简单并且即时渲染!


1
投票
inverted={1}

并使用 JS 反转函数反转数据。它对我有用


1
投票


1
投票

data={this.state.messages.reverse()}

let scrollRef = React.useRef(null)



0
投票

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


0
投票


0
投票


-1
投票

<FlatList ref={(it) => (scrollRef.current = it)} onContentSizeChange={() => scrollRef.current?.scrollToEnd({animated: false}) } data={data}/>

如果只想滚动到最后一条消息,可以使用initialScrollIndex

<Flatlist data={messageData} inverted={true} horizontal={false} />



-1
投票

我所做的是将

<Flatlist data={messageData} initialScrollIndex={messageArray.length - 1} horizontal={false} />

包裹在

FlatList
中,将
View
设置为反转,使其占据所有可用空间,然后调整内容。因此,现在,消息较少的对话从顶部开始,但当消息较多时,它们将在底部结束。像这样的东西:
FlatList

我的风格是这样的:

<View style={ConversationStyle.container}> <FlatList data={conversations} initialNumToRender={10} renderItem={({ item }) => ( <SmsConversationItem item={item} onDelete={onDelete} /> )} keyExtractor={(item) => item.id} getItemCount={getItemCount} getItem={getItem} contentContainerStyle={ConversationStyle.virtualizedListContainer} inverted // This will make items in reversed order but will make all of them start from bottom /> </View>

© www.soinside.com 2019 - 2024. All rights reserved.