Okay, this one's kind of weird, I know.
I'm trying to get a WebView to scroll within an Animated.ScrollView. Everything works, except that the WebView will only scroll after I move the Animated.View a certain distance. IMPORTANT NOTE: Animated.View
is != to Animated.ScrollView
. I don't mean to get confusing, but I need both in order for the page to work.
The return() code looks like this, I cut out some of the unnecessary code:
return(
<PanGestureHandler onGestureEvent={onGestureEvent2} >
<Animated.View style={[ styles.bottomHalf, animatedStyle2 ]}>
<Animated.ScrollView
nestedScrollEnabled={true}
scrollEnabled={true}
scrollEventThrottle={16}
contentContainerStyle={{ paddingTop: 25, paddingBottom: 50 }}
>
<GestureDetector gesture={panGesture}>
<View style={styles.container3}>
<WebView
ref={webviewRef}
source={{ uri: youtubeUrl }}
style={{ flex: 1 }}
onScroll={(event) => {
if(!isVerticalScroll.value) {
runOnJS(()=>{
if( webviewRef.current ){
webviewRef.current.scrollTo({
x: 0,
y: event.nativeEvent.contentOffset.y,
animated: false,
})
}
})
}
}
}
scrollEnabled={isVerticalScroll.value}
allowsFullscreenVideo={true}
/>
</View>
</GestureDetector>
</Animated.ScrollView>
</Animated.View>
</PanGestureHandler>
)
Note that in the above code I did not include the function that handles animatedStyle2
within the Animated.View
, this is b/c it works just fine. The imports and setting states, as well as the gesture handler panGesture
function look like this:
import { PanGestureHandler,Gesture, GestureDetector } from 'react-native-gesture-handler'
import Animated, { useSharedValue, runOnJS, useAnimatedStyle, withTiming, withSpring } from 'react-native-reanimated'
import { WebView } from 'react-native-webview'
const isVerticalScroll = useSharedValue(null)
const webviewRef = useRef(null)
const panGesture = Gesture.Pan().onStart(()=>{
console.log('Gesture Started');
isVerticalScroll.value = false
})
.onUpdate((event) => {
if (Math.abs(event.velocityY) > Math.abs(event.velocityX)) {
isVerticalScroll.value = true
} else {
isVerticalScroll.value = false
}
})
.onEnd(() => {
console.log('Gesture Ended');
});
The console.log() renders the 'Gesture Started' and 'Gesture Ended' messages just fine. The only problem is the WebView will not immediately scroll within its ScrollView like normal.
What I want: WebView within the Animated.ScrollView
to scroll immediately, without me having to move the Animated.View
at all.
What I'm getting: WebView will only scroll if I move the Animated.View
a certain distance.
Any help would be appreciated. I tried everything I could think of.
Okay, this one's kind of weird, I know.
I'm trying to get a WebView to scroll within an Animated.ScrollView. Everything works, except that the WebView will only scroll after I move the Animated.View a certain distance. IMPORTANT NOTE: Animated.View
is != to Animated.ScrollView
. I don't mean to get confusing, but I need both in order for the page to work.
The return() code looks like this, I cut out some of the unnecessary code:
return(
<PanGestureHandler onGestureEvent={onGestureEvent2} >
<Animated.View style={[ styles.bottomHalf, animatedStyle2 ]}>
<Animated.ScrollView
nestedScrollEnabled={true}
scrollEnabled={true}
scrollEventThrottle={16}
contentContainerStyle={{ paddingTop: 25, paddingBottom: 50 }}
>
<GestureDetector gesture={panGesture}>
<View style={styles.container3}>
<WebView
ref={webviewRef}
source={{ uri: youtubeUrl }}
style={{ flex: 1 }}
onScroll={(event) => {
if(!isVerticalScroll.value) {
runOnJS(()=>{
if( webviewRef.current ){
webviewRef.current.scrollTo({
x: 0,
y: event.nativeEvent.contentOffset.y,
animated: false,
})
}
})
}
}
}
scrollEnabled={isVerticalScroll.value}
allowsFullscreenVideo={true}
/>
</View>
</GestureDetector>
</Animated.ScrollView>
</Animated.View>
</PanGestureHandler>
)
Note that in the above code I did not include the function that handles animatedStyle2
within the Animated.View
, this is b/c it works just fine. The imports and setting states, as well as the gesture handler panGesture
function look like this:
import { PanGestureHandler,Gesture, GestureDetector } from 'react-native-gesture-handler'
import Animated, { useSharedValue, runOnJS, useAnimatedStyle, withTiming, withSpring } from 'react-native-reanimated'
import { WebView } from 'react-native-webview'
const isVerticalScroll = useSharedValue(null)
const webviewRef = useRef(null)
const panGesture = Gesture.Pan().onStart(()=>{
console.log('Gesture Started');
isVerticalScroll.value = false
})
.onUpdate((event) => {
if (Math.abs(event.velocityY) > Math.abs(event.velocityX)) {
isVerticalScroll.value = true
} else {
isVerticalScroll.value = false
}
})
.onEnd(() => {
console.log('Gesture Ended');
});
The console.log() renders the 'Gesture Started' and 'Gesture Ended' messages just fine. The only problem is the WebView will not immediately scroll within its ScrollView like normal.
What I want: WebView within the Animated.ScrollView
to scroll immediately, without me having to move the Animated.View
at all.
What I'm getting: WebView will only scroll if I move the Animated.View
a certain distance.
Any help would be appreciated. I tried everything I could think of.
Share Improve this question asked Feb 18 at 0:19 jedihomeslicejedihomeslice 477 bronze badges1 Answer
Reset to default 0Nevermind, guys. I figured it out.
I knew I needed a useEffect somewhere....
const webviewRef = useRef(null);
const translateY = useSharedValue(0);
const panGesture = Gesture.Pan()
.onUpdate((event) => {
translateY.value += event.changeY;
})
.onEnd(() => {
// Optionally add momentum or snapping behavior here
});
useEffect(() => {
// Reset translateY when the component mounts or dependencies change
translateY.value = 0;
}, []);
And the return....
<Animated.ScrollView
nestedScrollEnabled={true}
scrollEnabled={true}
scrollEventThrottle={16}
contentContainerStyle={{ paddingTop: 25, paddingBottom: 50 }}
>
<GestureDetector gesture={panGesture}>
<View style={styles.container3}>
<WebView
ref={webviewRef}
source={{ uri: youtubeUrl }}
style={{ flex: 1 }}
allowsFullscreenVideo={true}
nestedScrollEnabled
/>
</View>
</GestureDetector>
</Animated.ScrollView>
What a pain in the butt that was to figure out!