Cannot scroll inside GestureDetector on Android
shav95 opened this issue · comments
Here is my custom modal, I cannot scroll inside this modal
import {
Dispatch,
FC,
ReactNode,
SetStateAction,
useCallback,
useContext,
} from 'react';
import {
Platform,
Pressable,
Modal as ReactNativeModal,
ModalProps as ReactNativeModalProps,
StyleProp,
View,
ViewStyle,
} from 'react-native';
import Animated, {
FadeIn,
FadeOut,
runOnJS,
useAnimatedStyle,
useSharedValue,
} from 'react-native-reanimated';
import {CardWrapper, Icon, Loader} from 'molecules';
import {
GestureHandlerRootView,
GestureDetector,
Gesture,
} from 'react-native-gesture-handler';
import {useSelector} from 'react-redux';
import {getMainLoadingState, getPinState} from 'rtk';
import {IColor, ThemeContext} from 'theme';
import {modalStyles} from './modal-styles';
export interface ModalProps extends ReactNativeModalProps {
children: ReactNode | ReactNode[];
showLoader?: boolean;
isVisible: boolean;
setIsVisible: Dispatch<SetStateAction>;
swipeToClose?: boolean;
showCloseButton?: boolean;
showGrabber?: boolean;
backgroundColor?: IColor;
type?: 'modal' | 'bottom-sheet';
contentContainerStyles?: StyleProp;
activateAfterLongPress?: number;
}
const Modal: FC = ({
isVisible,
setIsVisible,
children,
showLoader = false,
swipeToClose = true,
showCloseButton = false,
showGrabber = true,
backgroundColor = 'surface_overlay',
type = 'modal',
contentContainerStyles = {},
activateAfterLongPress = 180,
...props
}) => {
const {color} = useContext(ThemeContext);
const isLoading = useSelector(getMainLoadingState);
// In Ios We Cannot Open Multiple Modals
// Our Pin Menu Is Inside A Modal And When We Open Pin Modal Over Another Opened Modal, It Will Not Work On IOS
const isPinVisible = useSelector(getPinState);
const translateY = useSharedValue(0);
const onClose = useCallback(() => {
translateY.value = 0;
setIsVisible(false);
}, [translateY.value]);
const panGesture = Gesture.Pan()
.onBegin(() => {
translateY.value = 0;
})
.onUpdate(event => {
if (event.translationY > 0 && swipeToClose)
translateY.value = event.translationY;
})
.onEnd(event => {
if (event.translationY > 100) {
if (onClose && swipeToClose) {
runOnJS(onClose)();
}
} else {
translateY.value = 0;
}
});
const simultaneousGesture = Gesture.Simultaneous(
panGesture,
Gesture.Native().disallowInterruption(false).shouldActivateOnStart(false),
);
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateY: translateY.value,
},
],
};
});
return (
<ReactNativeModal
{...props}
animationType="fade"
presentationStyle="overFullScreen"
visible={Platform.OS === 'ios' ? !isPinVisible && isVisible : isVisible}
transparent>
<Animated.View
entering={FadeIn}
exiting={FadeOut}
style={modalStyles({color, ...props}).animatedBackground}>
<Animated.View
style={[
modalStyles({type, ...props}).contentContainer,
animatedStyle,
]}>
<CardWrapper
backgroundColor={backgroundColor}
containerStyles={[
modalStyles({type, ...props}).container,
contentContainerStyles,
]}>
{showCloseButton && (
)}
{type === 'bottom-sheet' && showGrabber ? (
<View style={modalStyles({color}).grabber} />
) : null}
{children}
</CardWrapper>
</Animated.View>
</GestureDetector>
</GestureHandlerRootView>
</Animated.View>
<Loader isLoading={showLoader && isLoading} />
</ReactNativeModal>
);
};
export default Modal;