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

React native flatlist initial scroll to bottom

我正在尝试使用 <Flatlist />

在 React Native 中创建聊天

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

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

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

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

我怎样才能开始滚动到底部?

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

我猜 RN 无法猜出你的布局,所以它不知道它需要多少 "move"。根据文档中的滚动方法,您可能需要实现一个 getItemLayout 函数,以便 RN 可以知道它需要滚动多少。

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

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

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

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

如果你想让你的聊天消息从顶部开始,这就是我想要实现的。我无法在 FlatList 中找到解决方案,因为正如您所说,高度不同,我无法使用 getItemLayout,这使得 "scrollToEnd" 行为异常。

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

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

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

伙计们,如果你想让 FlatList 在初始渲染时滚动到底部。刚刚将 inverted={-1} 添加到您的 FlatList。我努力滚动到底部几个小时,但最终以 inverted={-1} 结束。无需考虑使用 getItemLayout 和 initialScrollIndex 或其他任何方式动态测量 FlatList 项目的高度。

<FlatList contentContainerStyle={{ flex: 1, justifyContent: 'flex-end' }} />

我也在这方面苦苦挣扎,并找到了对我来说渲染无故障的最佳解决方案是:

  1. 使用inverted={-1}道具
  2. 在我的例子中 data={this.state.messages.reverse()} 使用 reverse() javascript 函数 data={MyArrayofMessages.reverse()} 反转数组中消息对象的顺序。

非常简单,瞬间呈现!

使用 inverted={1} 并使用 JS 反转函数 反转数据。它对我有用

如果要反转显示消息,请在平面列表中将“inverted”设置为true。

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

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

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

我找到了 100% 适合我的解决方案

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

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

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

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

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


  • react-native 0.64.1
  • 反应 17.0.2

截至 2021 年,有两种 'good' 解决方案。 第一个是超时、引用和 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 } 
   />

我用反转 属性 和反向函数

解决了这个问题

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

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

我花了几个小时努力在顶部显示第一条消息,但无法计算项目的高度,因为它包含链接和消息。但我终于能够...

我所做的是将 FlatList 包裹在 View 中,将 FlatList 设置为反转,使其占用所有可用的 space 然后合理的内容。所以现在,消息很少的对话从顶部开始,但当有多个消息时,它们将在底部结束。像这样:

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

我的风格是这样的:

const ConversationStyle = StyleSheet.create({
    container: {
        flex: 1
    },

    virtualizedListContainer: {
        flexGrow: 1,
        justifyContent: 'flex-end'
    }
};

我找到了 100% 适合我的解决方案

  let scrollRef = React.useRef(null)

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