I have already managed with it.
@sendbird-uikit-react-native-foundation-npm-3.3.0-25f9e4acde.patch :
diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx
index fc798390cc467dc7a55e593631d5e4efdd1db00e..1cefc11e591b70e8e034a559a493bc9d7b5fc3c6 100644
--- a/src/components/Modal/index.tsx
+++ b/src/components/Modal/index.tsx
@@ -13,12 +13,16 @@ import {
TouchableWithoutFeedback,
ViewStyle,
useWindowDimensions,
+ BackHandler,
} from 'react-native';
+import Reanimated, { FadeIn, FadeOut } from 'react-native-reanimated';
import createStyleSheet from '../../styles/createStyleSheet';
import useHeaderStyle from '../../styles/useHeaderStyle';
import useUIKitTheme from '../../theme/useUIKitTheme';
+const AnimatedPressable = Reanimated.createAnimatedComponent(Pressable);
+
type ModalAnimationType = 'slide' | 'slide-no-gesture' | 'fade';
type Props = {
type?: ModalAnimationType;
@@ -53,7 +57,13 @@ const Modal = ({
const { topInset } = useHeaderStyle();
const [modalVisible, setModalVisible] = useState(false);
- const showAction = () => setModalVisible(true);
+ const showAction = () => {
+ if (Platform.OS === 'android') {
+ showTransition(() => setModalVisible(true))
+ } else {
+ setModalVisible(true)
+ }
+ };
const hideAction = () => hideTransition(() => setModalVisible(false));
const { width, height } = useWindowDimensions();
@@ -65,6 +75,70 @@ const Modal = ({
useOnDismiss(modalVisible, onDismiss);
+ const handleClose = () => {
+ onClose();
+ onDismiss?.();
+ }
+
+ useEffect(() => {
+ if (!visible) {
+ return;
+ }
+
+ const hardwareBackPress = () => {
+ handleClose();
+ return true;
+ }
+
+ BackHandler.addEventListener('hardwareBackPress', hardwareBackPress);
+ return () => {
+ BackHandler.removeEventListener('hardwareBackPress', hardwareBackPress);
+ };
+ }, []);
+
+ if (Platform.OS === 'android') {
+ if (visible) {
+ return (
+ <AnimatedPressable
+ style={[StyleSheet.absoluteFill, {
+ backgroundColor: palette.onBackgroundLight03,
+ }]}
+ onPress={() => {
+ if (!disableBackgroundClose) {
+ handleClose();
+ }
+ }}
+ entering={FadeIn}
+ exiting={FadeOut}>
+ <KeyboardAvoidingView
+ // NOTE: This is trick for Android.
+ // When orientation is changed on Android, the offset that to avoid soft-keyboard is not updated normally.
+ key={Platform.OS === 'android' && enableKeyboardAvoid ? `${width}-${height}` : undefined}
+ enabled={enableKeyboardAvoid}
+ style={styles.background}
+ behavior={Platform.select({ ios: 'padding', default: 'height' })}
+ pointerEvents={'box-none'}
+ keyboardVerticalOffset={enableKeyboardAvoid && statusBarTranslucent ? -topInset : 0}
+ >
+ <Animated.View
+ style={[
+ styles.background,
+ backgroundStyle,
+ { opacity: content.opacity, transform: [{ translateY: content.translateY }] },
+ ]}
+ pointerEvents={'box-none'}
+ {...panResponder.panHandlers}
+ >
+ {children}
+ </Animated.View>
+ </KeyboardAvoidingView>
+ </AnimatedPressable>
+ )
+ }
+
+ return null
+ }
+
return (
<RNModal
statusBarTranslucent={statusBarTranslucent}