I am trying to make Animated.ScollView to behave like a bottomSheet in Reactnative by using onScroll function in which I am getting contentOffsetY and based on that I make scrollView unmount/drag-down (works fine for IOS). But for Android it is not event triggering onScroll.
import * as React from 'react';
import { StyleSheet, Dimensions, Animated, View } from 'react-native';
const { width, height } = Dimensions.get('window');
import { Icon } from 'react-native-elements';
export const BottomSheet = ({
indicatorMargin,
heightFactor,
children,
gmRef,
dragging = true,
}) => {
const [alignment] = React.useState(new Animated.Value(height));
const [onAnimate, setOnAnimate] = React.useState(false);
const [isOpen, setIsOpen] = React.useState(false);
const scrollRef = React.useRef();
React.useEffect(
() => dragSheetUp(),
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
const dragSheetUp = React.useCallback(() => {
setOnAnimate(true);
setIsOpen(true);
Animated.timing(alignment, {
toValue: 0,
duration: 500,
useNativeDriver: false,
}).start(() => setOnAnimate(false));
scrollRef?.current?.scrollTo({
y: 0,
animated: true,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const dragSheetDown = React.useCallback(() => {
setOnAnimate(true);
Animated.timing(alignment, {
toValue: height,
duration: 500,
useNativeDriver: false,
}).start(() => {
setOnAnimate(false);
setIsOpen(false);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useImperativeHandle(
gmRef,
() => ({
open: () => dragSheetUp(),
close: () => dragSheetDown(),
}),
[dragSheetDown, dragSheetUp]
);
const actionSheetBottomStyle = {
top: alignment,
marginTop: height * (heightFactor - 1),
};
const gestureHandler = (e) => {
if (onAnimate) return;
if (e.nativeEvent.contentOffset.y < -40 && dragging) {
dragSheetDown();
}
};
const calculatedHeight = height * (heightFactor - 1) - 100;
return (
<Animated.ScrollView
ref={scrollRef}
style={[styles.bottomSheetContainer, actionSheetBottomStyle]}
scrollEventThrottle={12}
showsVerticalScrollIndicator={false}
onScroll={(e) => {
gestureHandler(e);
}}
>
{isOpen && dragging ? (
<View
style={styles.closeBtn}
onStartShouldSetResponder={() => {
dragSheetDown();
}}
>
<Icon name="chevron-down" type="feather" color="black" size={28} />
</View>
) : (
<View
style={[
styles.indicator,
{
marginBottom: indicatorMargin ? indicatorMargin : 10,
},
]}
/>
)}
{children}
<View style={[styles.bottomSpace, { height: calculatedHeight }]} />
</Animated.ScrollView>
);
};
const styles = StyleSheet.create({
bottomSheetContainer: {
backgroundColor: '#fff',
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
height: height / 1.2,
width: width / 1,
borderTopRightRadius: 20,
borderTopLeftRadius: 20,
paddingVertical: 10,
},
indicator: {
width: 30,
borderTopColor: 'black',
borderRadius: 15,
borderTopWidth: 4,
alignSelf: 'center',
},
bottomSpace: {
backgroundColor: '#fff',
},
closeBtn: {
width: 40,
alignSelf: 'center',
},
});
(Note: I want to handle onScroll even when we are at the top of ScrollView and it works fine for IOS but not for android)