如何在 RN 平面列表中获取当前可见的索引
Posted
技术标签:
【中文标题】如何在 RN 平面列表中获取当前可见的索引【英文标题】:How to get currently visible index in RN flat list 【发布时间】:2018-02-02 17:30:56 【问题描述】:我有一个水平平面列表,其中每个项目都是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。
【问题讨论】:
【参考方案1】:UPD。感谢@ch271828n 指出不应更新 onViewableItemsChanged
你可以使用 FlatList onViewableItemsChanged
prop 来得到你想要的。
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
【讨论】:
但是我怎么知道要使用哪些数据。因为项目是 300p 宽,如果它在中间,我会看到 20p 左右的项目,好的,我可以得到中间的。但是如果有两个项目如何选择下一个来获取它的数据。 此回调将所有三个项目返回为可见。只有完全消失的项目才会被标记为不可见。 我用图片更新了问题。当我在图像上看到两个项目时。我只需要获取一个项目数据(可能是比另一个更可见的项目数据)。这个回调有可能吗? 我更新了我的答案。我认为你现在可以尝试价值并得到你真正想要的 在 react native 0.54 中说:ExceptionsManager.js:65 Invariant Violation: Change on ViewableItemsChanged on the fly is not supported【参考方案2】:this.handleScroll = (event) =>
let yOffset = event.nativeEvent.contentOffset.y
let contentHeight = event.nativeEvent.contentSize.height
let value = yOffset / contentHeight
<FlatList onScroll=this.handleScroll />
获取舍入值以计算页码/索引。
【讨论】:
这个放在哪里? 好建议。在 android 上,onViewableItemsChanged 有时会将缓存的项目报告为可见项目。所以使用 handleScroll 或 onMomentumScrollEnd 与这个建议的计算要好得多。【参考方案3】:非常感谢投票最多的答案 :) 但是,当我尝试它时它不起作用,并引发错误说 changing onViewableItemsChanged on the fly is not supported
。经过一番搜索,我找到了解决方案here。这是可以无错误运行的完整代码。关键是这两个配置应该放在 类属性 中,而不是放在 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>
);
【讨论】:
我也遇到了这个问题,但我使用的是功能组件,而不是类。你有什么想法可以帮助我吗? 嗯,也许是useCallback
?我已经很多年没有写过 React...
@Josiah 你得到答案了吗?
聚会有点晚了,但这里是 Github 上问题的链接,其中一位贡献者提出了功能组件的解决方案。希望它会帮助某人github.com/facebook/react-native/issues/…【参考方案4】:
与@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
/>;
【讨论】:
_viewabilityConfig 应该使用 useMemo 创建或将其放在模块范围内的函数 MyComponent() 之外 我能问一下为什么吗? 最终用它来根据屏幕上的可见项目做一些事情,谢谢【参考方案5】:在你的情况下,我猜你可能会忽略 padding
或 margin
的项目。 contentOffsetX
或 contentOffsetY
应该是 firstViewableItemIndex
* (itemWidth
+ item padding or margin
)。
作为其他答案,onViewableItemsChanged
将是满足您要求的更好选择。我写了一篇关于如何使用它以及如何实现它的文章。
https://suelan.github.io/2020/01/21/onViewableItemsChanged/
【讨论】:
【参考方案6】:有点晚了,但对我来说功能组件不同......
如果您使用的是功能组件,请这样做:
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
/>
【讨论】:
在这种情况下,roundIndex 始终为 0 @manuel以上是关于如何在 RN 平面列表中获取当前可见的索引的主要内容,如果未能解决你的问题,请参考以下文章