将数据添加到 FlatList 始终显示第一个孩子

Posted

技术标签:

【中文标题】将数据添加到 FlatList 始终显示第一个孩子【英文标题】:Prepending data to a FlatList always shows the first child 【发布时间】:2019-11-04 13:40:56 【问题描述】:

这是我们的 FlatList,打个招呼:

<FlatList
    data=this.state.dates
...
/>

我们提供以下日期:

this.state = 
    dates: [
        '21/06/2019',
        '22/06/2019',
        '23/06/2019',
    ]
;

那么当可见日期发生变化时(onViewableItemsChanged),如果我们最终到达第一项(21/06/2019),我们会在前面添加数据,这样新的状态就变成了:

dates: [
        '18/06/2019',
        '19/06/2019',
        '20/06/2019',
        '21/06/2019',
        '22/06/2019',
        '23/06/2019',
]

问题:

在我们预先添加数据之后,我们现在看到的是 2019 年 6 月 19 日

这是因为在底层,21/06/2019 曾经是索引 0,但在前置后,索引 0 对应于 19/06/2019

我们想要什么:

我正在努力做到这一点,以便在预置数据后一天保持不变

请不要告诉我使用scrollToPosition,因为这确实是一种黑客行为,而不是解决方案。 这个问题有什么好的解决办法吗?

谢谢

【问题讨论】:

因为您要更改索引,所以如果没有scrollToIndex,我不明白您怎么能做到这一点(或者,这将更加骇人听闻)。如果你的物品高度相同,滚动会很快,你可以使用getItemLayout优化渲染。 您找到合适的解决方案了吗?我在我的项目中面临同样的问题。 没有,目前还没有 @SudoPlz 你找到解决办法了吗? 不是真的,所以我们最终在 react-native 上创建了自己的列表组件,我试图说服我们的管理层允许我们发布开源代码。 【参考方案1】:

有一个库:https://github.com/GetStream/react-native-bidirectional-infinite-scroll,它允许您预先准备或附加数据并保留滚动位置

它基本上是对 FlatList 的扩展,并支持普通 FlatList 可用的所有道具

来自他们的示例使用教程:https://dev.to/vishalnarkhede/react-native-how-to-build-bidirectional-infinite-scroll-32ph#%F0%9F%96%A5-tutorial-chat-ui-with-bidirectional-infinite-scroll

看起来只需像您尝试做的那样将该数据预先添加到顶部就足够了

【讨论】:

看起来很酷,但不适用于 Expo 管理的工作流程。【参考方案2】:

把这个留在这里,因为我花了一段时间才找到一个可行的解决方案/解决这个问题的方法,但不会让我觉得不好:用空数据预填充数组,然后使用 scrollToIndex 方法.

this.state = 
  dates: [
    '',
    '',
    '',
    '21/06/2019',
    '22/06/2019',
    '23/06/2019',
  ]
;

然后:

<FlatList
    data=this.state.dates
    ref=flatListRef
    getItemLayout=(data, index) => (
      length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index
    )
...
/>

在您的 componentDidMount 中:

const startingIndex = 4
flatListRef.current.scrollToIndex(index: startingIndex, animated: false, viewPosition: 0)

【讨论】:

确实如此,但您是否可以预先填充数据的合理数量(例如,您是否希望用户回溯到 2 年以上?)【参考方案3】:

如果您在 滚动位置 0(一直到顶部)时预先添加数据maintainVisibleContentPosition 将不起作用。如果您在 不是顶部 时进行前置,它确实有效。即使滚动 Y of 1 也足够了。

检查this

不幸的是,即使在React Native 0.63.3 中,这仍然是一个问题,并且尚未解决。

【讨论】:

【参考方案4】:

ScrollView 上有一个未记录的道具 maintainVisibleContentPosition 可以做你想做的事,但不幸的是它不适用于 android

我找到了另一种解决方法,使用onScroll 保持最新的 y 偏移量,并在使用 onContentSizeChange 添加新项目之前和之后保存内容高度并计算内容高度的差异,并将新的 y 偏移量设置为最新的 y 偏移量 +内容高度差!

我也开了issue on github,但还没有完整的解决方案 感谢 sgtpepper43 提供未记录的 ios 解决方案

【讨论】:

感谢您向我保证,我不是唯一面临该问题的人。看起来有人将不得不深入研究 Android 代码并为 Android 实现该标志。 我在iOS 上测试了maintainVisibleContentPosition。但是,如果您使用 append 数据,则此属性 only 有效。如果你 prepend 数据,它确实 not 工作。

以上是关于将数据添加到 FlatList 始终显示第一个孩子的主要内容,如果未能解决你的问题,请参考以下文章

在 React Native 中动态添加项目到 FlatList

React Native FlatList 可触摸不透明度

React Native FlatList 未显示

如何将默认类添加到vue中的第一个孩子

Flex React Native FlatList 孩子长到全高?

使用“let”关键字将数据传递给组件