React native 在项目大小可变的平面列表中滚动到特定索引的有效方法

React native 在项目大小可变的平面列表中滚动到特定索引的有效方法,react-native,React Native,在react native中将滚动/跳转添加到FlatList上的某些索引功能时遇到问题。我的平面列表项的大小(高度)不同,这使我无法实现getItemLayout,因为这需要我事先了解平面列表项的大小,因此我无法使用scrollToIndex(这需要实现getItemLayout) 我的解决方案是在使用onLayout渲染时获取每个项目的大小,并将它们与索引进行映射。然后,我可以使用每个项目大小获取其偏移量,并使用scrollToOffset跳转到给定的项目(使用下面代码中的scrollToI

在react native中将滚动/跳转添加到FlatList上的某些索引功能时遇到问题。我的平面列表项的大小(高度)不同,这使我无法实现
getItemLayout
,因为这需要我事先了解平面列表项的大小,因此我无法使用
scrollToIndex
(这需要实现
getItemLayout

我的解决方案是在使用
onLayout
渲染时获取每个项目的大小,并将它们与索引进行映射。然后,我可以使用每个项目大小获取其偏移量,并使用
scrollToOffset
跳转到给定的项目(使用下面代码中的
scrollToItem
函数)。这里的问题是,在渲染某个项目之前,我无法跳转到该项目。 我的临时解决方案是将
initialNumberToRender
调整到接近数据数量的位置,并将
windowSize
道具设置得尽可能高,以便渲染所有项目(即使用户没有向下滚动)

getOffsetByIndex=(索引)=>{
设偏移量=0;
for(设i=0;i{
const offset=this.getOffsetByIndex(索引);
此.flatListRef.scrollToOffset(偏移量);
};
addToLayoutMap=(布局、索引)=>{
this.layoutMap[index]=布局;
};
render(){
返回(
}
initialNumToRender={this.state.data.length/5}
WindowsSize={this.state.data.length}
/>
);
}
此解决方案适用于少量数据,但当数据较大(包含约300行)时,渲染需要很长时间才能获得所有项目大小,例如,防止用户直接跳到最后一个项目

有什么有效的方法吗?
此外,渲染所有行会占用大量内存,并否定了使用平面列表的好处。

您可以根据滚动方向动态分割数据。若向上滚动,则将数据前置到您的状态,并将数据前置到相反方向。然后像这样使用
onScrollToIndexFailed

<FlatList
  ref={this.flatListRef}
  data={this.state.data}
  renderItem={() => <View> <SomeComponent /> </View>}
  initialNumToRender={this.state.data.length / 5}
  onEndReached={(e) => {
    // Append data
  }}
  onScroll={(e) => {
    if (e.nativeEvent.contentOffset.y == 0) {
      // Prepend data
    }
  }}
  onScrollToIndexFailed={(error) => {
    this.flatListRef.scrollToOffset({ offset: error.averageItemLength * error.index, animated: true });
    setTimeout(() => {
      if (this.state.data.length !== 0 && this.flatListRef !== null) {
        this.flatListRef.scrollToIndex({ index: error.index, animated: true });
      }
    }, 100);
  }}
/>   
}
initialNumToRender={this.state.data.length/5}
onEndReached={(e)=>{
//附加数据
}}
onScroll={(e)=>{
如果(e.nativeEvent.contentOffset.y==0){
//前置数据
}
}}
onScrollToIndexFailed={(错误)=>{
this.flatListRef.scrollToOffset({offset:error.averageItemLength*error.index,动画:true});
设置超时(()=>{
if(this.state.data.length!==0&&this.flatListRef!==null){
this.flatListRef.scrollToIndex({index:error.index,动画:true});
}
}, 100);
}}
/>   

你可以解决这个问题。这对我来说很有效,并且花了我很多时间来完成这项工作:)

拆分数据并将其加载到scroll上。尝试滚动到最新的可见和可能的索引。然后使用
onScrollToIndexFailed
prop再次滚动到所需索引。如果这不起作用,我可以给你样品。谢谢你详细的回答。让我试着消化一下,以后再试试。一个简单的问题,你建议我使用
scrollToIndex
?因为当无法滚动到特定索引时,会调用
onScrollToIndexFailed
。我认为使用
scrollToIndex
需要实现
getItemLayout
,在我目前的情况下,由于项目的大小不同,无法准确实现
scrollToIndex
不依赖于
getItemLayout
。您可以随时使用scrollToIndex!我最终使用了
scrollToIndex
,并像您提供的那样使用了
onScrollToIndexFailed
。由于我上面提到的问题,我没有按照您的建议分割数据,仍然会有一些口吃,但还可以忍受。伙计,在失败了2个小时后,这终于对我有效了!我花了一年多的时间才意识到onScrollToIndexFailed是有用的。谢谢你,伙计。它是有效的。。。
<FlatList
  ref={this.flatListRef}
  data={this.state.data}
  renderItem={() => <View> <SomeComponent /> </View>}
  initialNumToRender={this.state.data.length / 5}
  onEndReached={(e) => {
    // Append data
  }}
  onScroll={(e) => {
    if (e.nativeEvent.contentOffset.y == 0) {
      // Prepend data
    }
  }}
  onScrollToIndexFailed={(error) => {
    this.flatListRef.scrollToOffset({ offset: error.averageItemLength * error.index, animated: true });
    setTimeout(() => {
      if (this.state.data.length !== 0 && this.flatListRef !== null) {
        this.flatListRef.scrollToIndex({ index: error.index, animated: true });
      }
    }, 100);
  }}
/>