edited to make it clearer:
I am trying to get the scroll distance from the current scroll position to the end of a list.
I am trying to distanceFromEnd value in a flatlist. I can get the scroll amount using onScroll however i cant get the amount the list can scroll. I can user layout to get the size of the scroll list but that amount is larger then the distance from end because it includes the non-scroll part (the size of the component). For now I am using onEndReached to get the distanceFromEnd but it would be much better if i could get the amount on component load. Does anyone know how to solve this problem? Thanks so much.
You should be able to know when each item in your FlatList mounts, renders, etc, which should give you the user's position in your list. Not in a position to write sample code at the moment, but if you're having trouble let me know.
Okay I worked it out. I can use
onScroll gets current scroll position
onLayout gets size of container
onContentSizeChange gets size of content
So distanceFromEnd = contentSize - contentContainer - scrollPosition
Related
I am trying to find the absolute position of a view. I can easily get its position using onLayout (#1 #2)
But this only gives the initial rendering position, but if the view is moved around due to scrolling, onLayout function is not firing again.
Can anyone please tell me if there is a way to get the absolute position after a change in view's position?
It will be awesome if there is a function or something that I can call with the view and, it will give its position.
Thanks
RCTUIManager does this same thing. Check out this example.
I am currently building an app which allows users to select their current weight and waist size. The list is long since, for example, the weight will start from 40kg up to 300kg, and each value will have a decimal point from .1 up to .9, e.g 40.0, 40.1, 40.2, 40.3, ... 40.9, 41.0, the whole numbers will be represented in a longer vertical line, while the decimal values in shorter vertical lines. So as you can imagine, the list is going to be really long. I have already implemented 2 ways: FlatList and Carousel using react-native-snap-carousel. They have their pros and cons, FlatList is much performant than the Carousel, but im having a hard time getting the value of the middle line. While the carousel performs poorly, i do have access to the current selected item. So my question here is: how do i implement this performance-wise and i have access with the currently selected item. Take Note also that i have implement FlatList's onViewableItemsChanged and it still doesn't achieve my goal
here is the screenshot of the UI:
In short:
You can check this library out: https://github.com/veizz/react-native-picker-scrollview
In detail:
There's a way to achieve this with some Flatlist props:
onScrollBeginDrag & onScrollEndDrag: detect when user starts/stops scrolling
onMomentumScrollBegin & onMomentumScrollBegin : detect scroll speed and momentum
scrollTo or scrollToIndex functions which requires Flatlist ref.
onScrollEvent if needed.
My opinion is, (which'll be my approach)
First, set the selectedItem as you like.
Then, using those scroll props above to detect which item(index) it's scrolling to. Select that item. Then scrollTo to selected.
Any point where it exceeds the threshold, use scrollTo or scrollToIndex to the next/previous item.
This is my approach, if you have your own, I'll be glad to discuss.
Happy coding!
The design of the application I am working on changes the layout based on the width of the device and there is a Flatlist component that calls scrollToIndex on the selected item so that it does not fall out side of the view when the app changes it's layout. If the last item is selected and scrolltToIndex is called, on iOS it will scroll the item all the way to the top and hide all the items above it. That makes it appear like it is the only item left and the only way to bring back the other items is to manually pull down the list. On android it works perfectly i.e it will only scroll an item high enough to fit as many items below it as possible (if more than height of container, it just scrolls it to the top).
From the FlatList>ScrollToIndex docs:
Note: Cannot scroll to locations outside the render window without specifying the getItemLayout prop.
Because FlatList is virtualized (i.e. efficient because it doesn't render the full list offscreen), it doesn't know the location of all of the elements (since they're not pre-rendered, and hence their size is unknown). It needs you to help by providing element sizes through getItemLayout to scroll beyond what's near visible. I suspect "near visible" may vary device to device with different memory settings. If you don't do this, you can end up with gaps in your list since exact placement is unknown.
So, you'll need to implement getItemLayout or use the less performant (and depricated) ListView component.
My ListView displays a feed of users, where each row is variable height (similar to Facebook).
A similar question suggests to scroll to rowIndex*rowHeight, but my rows are not the same height.
Any suggestions?
There is no simple way to do this. You can try to use onLayout event and save all rows height. But if part of rows before item you want scroll to was not rendered you can't calculate offset.
One solution in this situation is render all items at once. But there may be performance issue.
Another is scrolling bit by bit and calculate height in runtime.
My advice is redesign your UX to prevent this operation. Or use ScrollView and onLayout if row count is not too big.
UPDATED: FlatList will be added in RN 0.43. It has scrollToItem method.
I am currently using a ListView to display some data. Due to the design, the rows take up about 70% of the height of the screen which means there is always at least 2 rows visible, with a max of three. What I would like to determine is which row is mostly visible.
I am currently using onChangeVisibleRows, but that just tells me which rows are visible or have entered or left the view.
Any ideas?
This will only work when you know there are 2-3 (no more, no less) rows visible at a time:
onChangeVisibleRows={(visibleRows) => {
const visibleRowNumbers = Object.keys(visibleRows.s1).map((row) => parseInt(row));
if (visibleRowNumbers.length === 2) {
// visible row is visibleRowNumbers[0]
}
if (visibleRowNumbers.length === 3) {
// visible row is visibleRowNumbers[1]
}
}
Caveat being that it doesn't perfectly map to the row that is most visible is considered visible. However, in using it, it makes sense while scrolling. In my particular application, there is a visible shift between the active and inactive rows so it helps the user understand whats happened.
I don't have enough time to devise an accurate algorithm for your problem. But here is what you can do-
Get scroll position.
React native: get current scroll position of scrollview
Get screen height.
https://facebook.github.io/react-native/docs/dimensions.html#content
Calculate approx. height of ListView child.
You can leverage these three things to find out how much space has been taken by a specific child.
By getting scroll position you can know how many pixels have you scrolled down. Divide that by height of your child, so that you can get how many children have been scrolled by the user.
(Scrolled height / Child height) = No. of children scrolled.
And finally, onChangeVisibleRows will tell you which children are visible. Good luck!