[Bug][iOS]: Incorrect keyboardBlurBehavior="restore" + keyboardBehavior="extend" Behavior in BottomSheetModal
Version
v5
Reanimated Version
v3
Gesture Handler Version
v2
Platforms
iOS
What happened?
This is the same thing originally posted in https://github.com/gorhom/react-native-bottom-sheet/issues/1887 which was closed.
Expected As a user, when I dismiss a keyboard, the bottom sheet modal should go back to its original position
Actual on iOS the bottom sheet does not go back to default/previous position.
https://github.com/user-attachments/assets/3fed0890-3529-48c1-80b9-6bf6c4a2acd7
Reproduction steps
- ensure prop
keyboardBehavior="extend" - Open Snack link
- Present Modal
- Focus the input
- you will see keyboard appears + modal shifts up 👍
- Press "done" button on keyboard
- you will see keyboard disappears + modal stays shifted up 👎
Reproduction sample
https://snack.expo.dev/@lucksp/bottom-sheet---issue-reproduction-template
Relevant log output
Similar thing is happening for me. I have keyboardBehavior="interactive" when I open the keyboard the sheet moves up and when I dismiss the keyboard sheet remains at the top. This part of the code is not returning the correct index. I have managed to put a fix in my locally installed package code. Basically the currentIndex in this code is incorrect when keyboard closes:
I fixed it locally by going into the node_modules and gorhom folder, finding this section in BottomSheet component and adding this in the if statement:
if ( source === ANIMATION_SOURCE.KEYBOARD && keyboardBlurBehavior === KEYBOARD_BLUR_BEHAVIOR.restore && keyboardStatus === KEYBOARD_STATUS.HIDDEN && animatedContentGestureState.value !== State.ACTIVE && animatedHandleGestureState.value !== State.ACTIVE ) { isInTemporaryPosition.value = false; // return the previously active detent position when available, // otherwise fall back to the first detent const nextPosition = currentIndex >= 0 && detents && currentIndex < detents.length ? detents[currentIndex] : detents[0]; return nextPosition; }
@HassanKhan96 it doesn't work in my case.
<BottomSheet
ref={sheetRef}
index={-1}
snapPoints={snapPoints}
enableDynamicSizing={false}
onChange={onChangeSheet}
enablePanDownToClose
backdropComponent={renderBackdrop}
keyboardBehavior="interactive"
keyboardBlurBehavior="restore"
android_keyboardInputMode="adjustPan"
enableBlurKeyboardOnGesture={true}
containerStyle={{ marginTop: insets.top }}
enableOverDrag={false}
handleStyle={{ backgroundColor: handleBackgroundColor }}
>
.......
</BottomSheet>
It works fine here on Android and iOS (native), but when I access it on the iOS web interface, BottomSheetModal behaves strangely when focusing on inputs. Does anyone know how to solve this?
import React, { useEffect, useRef } from "react";
import { View, Platform } from "react-native";
import { useTheme } from "styled-components/native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useSheet } from "@/store/sheet";
import {
BottomSheetModal,
BottomSheetModalProvider,
BottomSheetScrollView,
} from "@gorhom/bottom-sheet";
import { Button } from "@/components/ui/button";
import { X } from "lucide-react-native";
import { DEFAULT_PADDING } from "@/components/layout-constants";
export const SheetRoot = () => {
const theme = useTheme();
const insets = useSafeAreaInsets();
const { content, isVisible, closeSheet, snapPoints } = useSheet();
const modalRef = useRef(null);
useEffect(() => {
const timeout = setTimeout(() => {
if (isVisible) {
modalRef.current?.present();
} else {
modalRef.current?.dismiss();
}
}, 0);
return () => clearTimeout(timeout);
}, [isVisible]);
return (
<BottomSheetModalProvider>
<BottomSheetModal
ref={modalRef}
onDismiss={closeSheet}
snapPoints={snapPoints}
keyboardBehavior="interactive"
keyboardBlurBehavior="restore"
enablePanDownToClose={Platform.OS !== "web"}
android_keyboardInputMode="adjustResize"
handleComponent={Platform.OS === "web" ? null : undefined}
backdropComponent={({ style }) => (
<View style={[style, { backgroundColor: "rgba(0, 0, 0, 0.85)" }]} />
)}
backgroundComponent={({ style }) => (
<View style={(style, { backgroundColor: theme.colors.background })} />
)}
handleIndicatorStyle={{
backgroundColor: theme.colors.input,
marginTop: 8,
}}
handleStyle={{
backgroundColor: theme.colors.background,
}}
style={{
backgroundColor: theme.colors.background,
}}
>
<BottomSheetScrollView
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
contentContainerStyle={{
paddingHorizontal: DEFAULT_PADDING,
paddingTop: DEFAULT_PADDING / 2,
paddingBottom: insets.bottom + DEFAULT_PADDING,
backgroundColor: theme.colors.background,
}}
>
<View
style={{
maxWidth: 600,
width: "100%",
margin: "auto",
}}
>
{Platform.OS === "web" && (
<View style={{ alignItems: "flex-end" }}>
<Button variant="ghost" size="icon" onPress={closeSheet}>
<X size={18} />
</Button>
</View>
)}
{content || null}
</View>
</BottomSheetScrollView>
</BottomSheetModal>
</BottomSheetModalProvider>
);
};