I have a horizontal flat list where each item is width:300
All I am trying to do is to get index of currently visible item.
UPD. thanks to @ch271828n for pointing that onViewableItemsChanged shouldn`t be updated
You can use FlatList onViewableItemsChanged
prop to get what you want.
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
can help you to make whatever you want with viewability settings. In code example 50
means that item is considered visible if it is visible for more than 50 percents.
Config stucture can be found here
With related to @fzyzcjy's and @Roman's answers. In react, 16.8+ you can use uscCallback
to handle the changing onViewableItemsChanged on the fly is not supported
error.
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}
/>;
}
this.handleScroll = (event) => {
let yOffset = event.nativeEvent.contentOffset.y
let contentHeight = event.nativeEvent.contentSize.height
let value = yOffset / contentHeight
}
<FlatList onScroll={this.handleScroll} />
Get the round-off value to calculate the page-number/index.
In your case, I guess, you might ignore the padding
or margin
of items. The contentOffsetX
or contentOffsetY
should be firstViewableItemIndex
* (itemWidth
+ item padding or margin
).
As other answers, onViewableItemsChanged
would be a better choice to meet your requirement. I wrote an article about how to use it and how it is implemented.
https://suelan.github.io/2020/01/21/onViewableItemsChanged/
Many thanks to the most-voted answer :) However, it does not work when I try it, raising an error saying that changing onViewableItemsChanged on the fly is not supported
. After some search, I find the solution here. Here is the full code that can run without error. The key point is that the two configs should be put as class properties instead of inside the render() function.
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>
);
}
}