如何在 RN 平面列表中获取当前可见的索引

How to get currently visible index in RN flat list

我有一个水平平面列表,其中每个项目都是 width:300 我要做的就是获取当前可见项目的索引。

<FlatList 
            onScroll={(e) => this.handleScroll(e)} 
            horizontal={true}
            data={this.state.data}
            renderItem...

试过这个:

handleScroll(event) {
    let index = Math.ceil(
      event.nativeEvent.contentOffset.x / 300
    );

还有这样的东西:

handleScroll(event) {
  let contentOffset = event.nativeEvent.contentOffset;
  let index = Math.floor(contentOffset.x / 300);

但没有什么是准确的我总是得到一个索引向上或向下一个索引。
我做错了什么以及如何在平面列表中获得正确的当前索引?

例如,我列出了列表中第 8 位的项目,但我得到的索引是 9 或 10。

UPD。感谢 @ch271828n 指出不应更新 onViewableItemsChanged

你可以使用 FlatList onViewableItemsChanged 属性来获得你想要的东西。

class Test extends React.Component {
  onViewableItemsChanged = ({ viewableItems, changed }) => {
    console.log("Visible items are", viewableItems);
    console.log("Changed in this iteration", changed);
  }

  render () => {
    return (
      <FlatList
        onViewableItemsChanged={this.onViewableItemsChanged }
        viewabilityConfig={{
          itemVisiblePercentThreshold: 50
        }}
      />
    )
  }
}

viewabilityConfig 可以帮助您随心所欲地设置可见度。在代码示例中,50 表示如果该项目的可见度超过 50%,则该项目被视为可见。

可以找到配置结构here

this.handleScroll = (event) => {
  let yOffset = event.nativeEvent.contentOffset.y
  let contentHeight = event.nativeEvent.contentSize.height
  let value = yOffset / contentHeight
}

<FlatList onScroll={this.handleScroll} />

获取舍入值以计算 page-number/index。

非常感谢投票最多的答案:) 但是,当我尝试它时它不起作用,并引发错误说 changing onViewableItemsChanged on the fly is not supported。经过一番搜索,我找到了解决方案here。这是可以 运行 没有错误的完整代码。关键是这两个配置应该放在 class properties 而不是在 render() 函数中。

class MyComponent extends Component {  
  _onViewableItemsChanged = ({ viewableItems, changed }) => {
    console.log("Visible items are", viewableItems);
    console.log("Changed in this iteration", changed);
  };

  _viewabilityConfig = {
    itemVisiblePercentThreshold: 50
  };

  render() {
    return (
        <FlatList
          onViewableItemsChanged={this._onViewableItemsChanged}
          viewabilityConfig={this._viewabilityConfig}
          {...this.props}
        />
      </View>
    );
  }
}

与@fzyzcjy 和@Roman 的回答相关。在 React 中,16.8+ 可以使用 useCallback 来处理 changing onViewableItemsChanged on the fly is not supported 错误。

    function MyComponent(props) {
        const _onViewableItemsChanged = useCallback(({ viewableItems, changed }) => {
            console.log("Visible items are", viewableItems);
            console.log("Changed in this iteration", changed);
        }, []);
    
        const _viewabilityConfig = {
            itemVisiblePercentThreshold: 50
        }
    
        return <FlatList
                onViewableItemsChanged={_onViewableItemsChanged}
                viewabilityConfig={_viewabilityConfig}
                {...props}
            />;
    }

在您的情况下,我想您可能会忽略项目的 paddingmargincontentOffsetXcontentOffsetY 应该是 firstViewableItemIndex * (itemWidth + item padding or margin)。

与其他答案一样,onViewableItemsChanged 将是满足您要求的更好选择。我写了一篇关于如何使用它以及它是如何实现的文章。 https://suelan.github.io/2020/01/21/onViewableItemsChanged/

有点晚了,但对我来说功能组件是不同的...

如果您使用的是功能组件,请这样做:

  const onScroll = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {
    const slideSize = event.nativeEvent.layoutMeasurement.width;
    const index = event.nativeEvent.contentOffset.x / slideSize;
    const roundIndex = Math.round(index);
    console.log("roundIndex:", roundIndex);
  }, []);

然后在你的 FlatList 上

<FlatList
      data={[2, 3]}
      horizontal={true}
      pagingEnabled={true}
      style={{ flex: 1 }}
      showsHorizontalScrollIndicator={false}
      renderItem={renderItem}
      onScroll={onScroll}
    />