How to solve React Native Scroll Animation issue during slow scroll? - react-native

I have made an example code here with Snack expo
Animated Header
The issue that I'm having is that my animation is not smooth enough.
It looks like it's shaking.
Demo video YouTube Video
I can't seem to find what's the issue here and also tried to fiddle around with the scrollEventThrottle, alwaysBounceVertical, bounces, bouncesZoom props in ScrollView.

I figure out what the problem is and the issue is not because of the performance.
The problem is because of the styling on the header.
Adding the position to absolute will solve this problem.
But there's another issue that appeared when having the position as absolute, the component inside the header such as TextInput won't appear when a touch event occurs.
To solve this new issue, you have to add the zIndex.
More tutorial about zIndex
Animated Header Fixed

Try adding useNativeDriver:
onScroll={
Animated.event([
{
nativeEvent: {
contentOffset: {
y: scrollY,
},
},
},
],
{ useNativeDriver: true })
}
But I think in React Native, ScrollView is not supposed to work with extremely long duplicated content. I suggest you to use a flatlist for your use case.

Adding removeClippedSubviews = {true} on top most ScrollView solved my issue and app performance feels so light.

Related

Janky translateY on Reanimated View inside of ScrollView as user scrolls

I am using react-native-reanimated v1. I want to make a <Reanimated.View> appear as if it is fixed within the scroll view by using translateY. GIF of how of it should behave is at very end of post. I have simplified the code in the snippet below, and I have the full working code in the snack.
https://snack.expo.io/#noitidart/reanimated-scroll-view
As you scroll, you notice the position of the view is not staying fixed at the top. I attached a video taken on iOS of the snack.
If I add scrollEventThrottle={16} it fixes the issue on iOS, but on Android if you scroll even a little faster than normal you see the transform is lagging. I think there should be a way on iOS without the scrollEventThrottle property too, it doesn't make sense to me that we need this as reanimated is supposed to update every frame.
Any ideas on how to fix this?
const ReanimatedScrollView = Reanimated.createAnimatedComponent(ScrollView);
export default function App() {
const translateY = Reanimated.useValue(0);
const handleScroll = Reanimated.event([
{
nativeEvent: nativeEvent => Reanimated.block([Reanimated.set(translateY, nativeEvent.contentOffset.y)])
}])
return (
<ReanimatedScrollView onScroll={handleScroll}>
<Reanimated.View style={{ transform: [{ translateY }] }} />
</ReanimatedScrollView>
);
}
Janky on iOS
Janky on Android (with and without scrollEventThrottle={16})
Here is video of how it should be (with scrollEventThrottle={16} on iOS, but it doesn't fix up Android)

react-native-webview avoid keyboard (iOS)

The react-native-webview has in my experience proved difficult to behave as I want around the keyboard on iOS. It doesn't automatically change it's height when the keyboard is shown and its contents gets concealed by the keyboard.
It also behaves strangely wrapped with the KeyboardAvoidingView. In my case it seems to adjust the content of the WebView too much, approximately twice the height of the keyboard. This same behavior appeared when I manually listened for the keyboard open/close events and adjusted the height of the WebView accordingly:
componentDidMount(){
Keyboard.addListener("keyboardWillShow", this.keyboardDidShow.bind(this));
Keyboard.addListener("keyboardWillHide", this.keyboardDidHide.bind(this));
}
componentWillUnmount(){
Keyboard.removeListener("keyboardWillShow", this.keyboardDidShow.bind(this));
Keyboard.removeListener("keyboardWillHide", this.keyboardDidHide.bind(this));
}
keyboardDidShow(event){
this.setState({
keyboardHeight: event.endCoordinates.height
});
}
keyboardDidHide(event){
this.setState({
keyboardHeight: 0
});
}
render(){
return (
<WebView
style={{flex: 1, maxHeight: Dimensions.get("window").height - this.state.keyboardHeight}}
/>
);
}
I've found a solution, not optimal, but a solution non the less. My answer is posted below.
As I couldn't find any discussions on this particular behavior and no solutions that worked for me, I worked my way through the props of the react-native-webview docs. What finally worked for me in version 0.59.9 of React Native and version 5.11.0 of React Native WebView was as described above, manually setting the height of the WebView in the keyboard event listeners and setting the WebView prop useWebKit={false}.
Unfortunately this means that on the native side of the WebView, it's now using UIWebView which is deprecated and will in a future release be deleted.
Either way, this is what I'm rolling with and simply wanted to share my findings in case anyone finds themselves with the same issue.

React Native Animated Scroll view jump behavior

Stuck with small problem. I have Animated.ScrollView and there i have onScroll Event like this
Animated.event(
[
{
nativeEvent: {
contentOffset: {
x: this.topViewAnimation,
},
},
},
],
{ useNativeDriver: true },
)
So onScroll that card which active ( on the screen ) highlights item in view.
Sometimes i need to scroll to specific value with scrollTo method but i always see one problem.
For example i have 10 items. ( 10 items in view and 10 items which i will highlight based on scrollOffset ).
When i will use my scrollTo method i will see how every item highlights untill it become this one what i need.
Is there a way to highlight only one item what i need?
I've just jumped into the same problem today, and after hours trying to solve this issue, the solution was quite straightforward.....
What I did is to NOT TO USE the Animated.ScrollView component, and instead, I created a new ScrollView animated component whith the animated interface:
const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView)
Then I used this new "AnimatedScrollView" component insted of the "Animated.ScrollView" and everything run just smoothly...
Good luck!

React native synchronize two flatlist smoothly

I have two flatlist, one contains the data (dataScroll) and the other the checkboxes (checkScroll) for every data item.
The reason for this is that the checkboxes have to be always visible while the user scrolls horizontaly on the dataScroll (I put the dataScroll in a horizontally scrollable scrollview).
Demo:
expo snack demo
Tried so far:
On dataScroll's scroll event, I got the y offset and moved the checkScroll to that y position.
handleDataScroll = ({ nativeEvent: { contentOffset: { y } } }) => {
this.checkScroll.scrollToOffset({ offset: y, animated: true });
}
It (almost) does the job, but there is a huge delay between the 2 flatlist while scrolling.
--
I read that maybe the use of animated components the way to go, but I couldn't figure out how the animation works in react native.
So I'd like to get some help on how should I bind the two flatlist together so that if I scroll on one list, the other follows it with no (or at least minimal) delay.
If only the dataScroll flatlist is scrollable that's ok too.

React native detect screen rotation

I'm using onLayout to detect screen orientation and it's working fine inside my root view, but when I implemented inside the drawer it didn't work, any reason why this happens ?
code :
import Drawer from 'react-native-drawer'
...
onLayout(e) {
console.log('onLayout');
}
<Drawer onLayout={this.onLayout}
It didn't log any thing when orientation changed!
This is because the Drawer component doesn't take onLayout as a prop. You can see in the source code that the rendered View does use onLayout, but it's not pulling from something like this.props.onLayout.
I'm not exactly sure what you're looking to do, but maybe this issue will help you. As it shows, you can pass a function into openDrawerOffset instead of an integer or a ratio in order to be a little more dynamic with how you set your offset:
openDrawerOffset={(viewport) => {
if (viewport.width < 400) {
return viewport.width * 0.1;
}
return viewport.width - 400;
}}
You might also benefit from the Event handlers that react-native-drawer has to offer.