In my case, I want to change some states only when the ScrollView is not gliding. I would like to know is there any way to implement it like list.stopGliding() or list.stopScrollMomentum()?
You can use:
onMomentumScrollBegin: Called when the momentum scroll starts (scroll which occurs as the ScrollView starts gliding).
and:
onMomentumScrollEnd: Called when the momentum scroll ends (scroll which occurs as the ScrollView glides to a stop).
or you can use:
onScrollBeginDrag: Called when the user begins to drag the scroll view.
and
onScrollEndDrag: Called when the user stops dragging the scroll view and it either stops or begins to glide.
If you want to stop all the momentum, you can use the prop:
decelerationRate={0}
To read more here's the documentation
Related
What I am trying to accomplish:
I have a horizontal flatlist (with pagination: true) and I would like to animate the scrolling depending on where on the y axis the user started swiping from.
If the scrolling started from the upper half of the flatlist then its border would animate to a certain color, otherwise it would switch to a different color, and depending on the scroll start position I would call a different function when the next index when the next index is scrolled to.
My question:
So is it possible to use a gesture responder (from react-native-gesture-handler) to handle the scrolling instead of relying on the built in responder of flatList?
for example: calling scrollToOffset repeatedly from inside my gesture responder or set a "current scroll position" prop with an animated value and pass it to the flatList component? no matter what I try I get bombarded with obscure error messages so I was wondering if it is even possible.
I have a ScrollView (actually Animated.ScrollView) that I'd like to decide whether to allow vertically scroll or not on scroll start, based on some states of inner components. I know there is a scrollEnabled property which works but the scroll view contains some components that that a few frames to render and changing scrollEnabled property based on inner views' interactions cause a re-render, which drops a few frames and because of the nature of my app needing to change this property based on some animation/smooth scrolling of the inner views, those dropped frames cause a negative user experience.
I've also tried preventDefault of the scroll begin drag event but nothing changed (it allows scrolling regardless of I call it or not).
How can I decide whether or not to allow scrolling of scroll view dynamically on scroll start without a state/props update (which causes a re-render of an expensive view tree, dropping frames)? Something like pan responder's onMoveShouldSetPanResponder[Capture] events might be of great help but returning false from them just don't work (it captures and scrolls regardlessly even though they are called). (I'm on React Native 0.64)
After reading the post in https://codedaily.io/courses/Master-React-Native-Animations/Using-and-Understanding-setNativeProps I solved it by setting native props on scroll view (that I reference directly using a ref) instead of updating state, preventing a re-render:
this.state.scrollView.current?.setNativeProps({
scrollEnabled: false
});
I watched this presentation and there's a section on how to build an IOS Maps like UI. When dragging from the bottom to top, it drags to the top, and after it reaches the top, it continues scrolling up. Also, when scrolling down, when it reached the top content of the ScrollView, it continues to drag down.
It is suggested that it can be done using ScrollView by adding an empty transparent cell as the first element on the ScrollView. I have tried implementing the same which can be found in this snack. In my case, instead of Maps, I am using another ScrollView.
But the problem is that the first element (transparent element) does not allow to interact with the First ScrollView elements. I have tried with pointerEvents inside the first transparent view and even in its parent ScrollView. But this does not help. Has anyone tried implementing this kind of use case with react-native? All I found was this library, but I think it's not maintained properly.
you need to set the z-index of the transparent view to send it under/behind the interactive content, here is a good resource:
https://philipwalton.com/articles/what-no-one-told-you-about-z-index/
Edit: Actually I could not accomplish it, it seems like everything inside a scrollview will always be behind or in front of other elements, it seems like you can't have part of the scrollview behind something else and another part in front of something else.
I'm attempting to create a custom NavBar on a screen that renders a ScrollView. Inside the NavBar, there's a button, that when pressed, causes the NavBar to translate downwards, thereby giving the appearance that the NavBar is expanding (This is done using Animated.spring() with the useNativeDriver option). Everything is working great, except if the ScrollView is still scrolling at the time the button is tapped (ie: when "momentum" scroll is taking place). In this scenario, the onPress handler that kicks off the NavBar animation is invoked as expected, but calls to Animated.spring() do not cause any animation to take place. Is it possible to either have the NavBar "expansion" animation to occur during the scroll, or pause the scroll to allow animation to proceed?
Like it's explained in RN docs the animation type you using are stoped by gesture events like scrolling, better use Animated.event() with onScrollprops combined with an interpolation animation to animate you footer.
I would like to create a carousel that scrolls automatically until the user scrolls / touches the ScrollView itself.
The auto-scrolling itself works fine with using scrollView.scrollTo but how could I detect if the user is interacting with the ScrollView? I took a look at the onScroll event but this does not seem to distinct between a user generated event and an event that was generated by calling scrollTo.
Also I'd like to know if it is possible to get the current scroll position from the ScrollView directly instead of reading it everytime from the onScroll event.
I'm very thankful for any tips and suggestions.
By digging into ScrollView's source code you can notice a few undocumented callbacks that will help you achieve what you're after, namely onTouchStart and onTouchEnd. These two callbacks are triggered only when user interacts with the ScrollView and not when you scroll programmatically.
You will probably want to clear your auto-scroll interval on onTouchStart and restart it after a delay on onTouchEnd.
Regarding your next question, the answer is no. As far as I know, no getter is currently exposed to retrieve the current scroll position. Therefore, you need to rely on the event passed to onScroll, retrieve event.nativeEvent.contentOffset['x' or 'y'], and store it in your component's state.
Note that if you're doing some heavy animations that need to follow scroll position closely (e.g. animated header or parallax image), it would be a good idea to use the native driver for Animated.event. You can learn more about it on React Native's blog.