You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native @gorhom/bottom-sheet键盘关闭时自动展开问题求助

React Native Bottom Sheet 自动展开问题

依赖版本

"@gorhom/bottom-sheet": "^4",
"@hookform/resolvers": "^3.0.0",
"@react-navigation/drawer": "^6.6.2",
"@react-navigation/native": "^6.1.6",
"@react-navigation/stack": "^6.3.16",
"react-hook-form": "^7.43.8",
"react-native": "0.71.4",
"react-native-paper": "^5.5.2",

问题描述

TextInput 不在 BottomSheet 组件内部,但当 TextInput 获取焦点后,关闭键盘或让输入框失焦时,bottom sheet 会自动展开,而非通过 ref 对象触发。

应用最简配置

App.ts

const App = () => {
  return (
    <PaperProvider theme={theme}>
        <NavigationContainer onReady={RNBootSplash.hide}>
        <PortalProvider>
          <AppNavigator />
        </PortalProvider>
        </NavigationContainer>
      </PaperProvider>
  );
}

AppNavigator.ts

const Stack = createStackNavigator();

const AppNavigator = () => {
    return (
        <>
            <Stack.Navigator
                detachInactiveScreens={true}
                screenOptions={{ 
                    animationEnabled: true, 
                    headerShown: false, 
                    cardStyleInterpolator: CardStyleInterpolators.forScaleFromCenterAndroid 
                }}
                initialRouteName={ScreenRouteEnum.HOME}
            >
                <Stack.Screen name={ScreenRouteEnum.HOME} component={MainScreen} />
                <Stack.Screen name={ScreenRouteEnum.ADD_POLE} component={AddPole} />
            </Stack.Navigator>
            <PortalHost name="addPolePortal" />
        </>
    );
};

AddPole.ts

const voltage = [
    {
      pole_voltage_id: 1,
      pole_voltage_name: '69KV'
    }
  ]
  
  
const AddPole = () => {
    const snapPointsVoltage = useMemo(() => ['25%'], []);
     const bottomSheetRef = useRef<BottomSheet>(null);

    const renderBackdrop = useCallback(
        (props: any) => (
            <BottomSheetBackdrop
                {...props}
                disappearsOnIndex={-1}
                appearsOnIndex={0}
            />
        ),
        []
    );

    const handleSheetChanges = useCallback((index: number) => {
        console.log('handleSheetChanges', index);
      }, []);
     
    const onOpenSheet = () => {
       bottomSheetRef?.curret?.collapse();
    }

    return (
            <>
             <TextInput placeholder="Write something" />
             <Button onClick={onOpenSheet}>
                Open Sheet
             </Button>
             <Portal hostName="addPolePortal">
                <BottomSheet
                    ref={bottomSheetRef}
                    index={-1}
                    snapPoints={snapPointsVoltage}
                    enablePanDownToClose
                    onChange={handleSheetChanges}
                    backdropComponent={renderBackdrop}
                    handleIndicatorStyle={{ backgroundColor: '#a1a1a1' }}
                >
                    <BottomSheetView style={styles.bottomSheetContainer}>
                        {voltage.map(a => (
                            <TouchableRipple
                                key={a.pole_voltage_id}
                                style={styles.menuItemInner} 
                                rippleColor="rgba(0, 0, 0, .1)" 
                                onPress={onPress}
                              >
                                <Text style={styles.menuText}>{a.pole_voltage_name}</Text>
                            </TouchableRipple>
                        ))}
                    </BottomSheetView>
                </BottomSheet>
             </Portal>
         </>
    );
}

const styles = StyleSheet.create({
    bottomSheetContainer: {
        paddingVertical: 15,
        flex: 1
    },
})


export default AddPole;

已尝试的解决方法

设置 keyboardBlurBehavior="none",但问题未解决。


解决方案

1. 禁用BottomSheet的键盘交互

@gorhom/bottom-sheet 默认会监听键盘事件调整自身状态,即使输入框不在Sheet内也可能触发异常。可以通过 keyboardBehavior 属性完全禁用键盘相关自动调整:

<BottomSheet
  ref={bottomSheetRef}
  index={-1}
  snapPoints={snapPointsVoltage}
  enablePanDownToClose
  onChange={handleSheetChanges}
  backdropComponent={renderBackdrop}
  handleIndicatorStyle={{ backgroundColor: '#a1a1a1' }}
  keyboardBehavior="none" // 添加此属性
/>

2. 手动控制Sheet的启用状态

在TextInput焦点变化时,手动禁用/启用Sheet的交互能力,避免键盘事件误触:

const AddPole = () => {
  // ... 其他代码
  const [inputFocused, setInputFocused] = useState(false);

  return (
    <>
      <TextInput 
        placeholder="Write something"
        onFocus={() => setInputFocused(true)}
        onBlur={() => setInputFocused(false)}
      />
      <Portal hostName="addPolePortal">
        <BottomSheet
          // ... 其他属性
          enabled={!inputFocused} // 输入框聚焦时禁用Sheet交互
        >
          {/* ... Sheet内容 */}
        </BottomSheet>
      </Portal>
    </>
  );
}

3. 修正代码拼写错误

注意到 onOpenSheet 函数中 bottomSheetRef?.curret?.collapse() 存在拼写错误,curret 应为 current,且如果是要打开Sheet,应该用 expand() 而非 collapse():

const onOpenSheet = () => {
  bottomSheetRef?.current?.expand();
}

4. 调整Portal层级

尝试将BottomSheet移出Portal,直接放在AddPole组件的根容器内,排查是否是Portal层级导致的事件冒泡问题:

return (
  <View style={{ flex: 1 }}>
    <TextInput placeholder="Write something" />
    <Button onClick={onOpenSheet}>
      Open Sheet
    </Button>
    <BottomSheet
      ref={bottomSheetRef}
      index={-1}
      snapPoints={snapPointsVoltage}
      enablePanDownToClose
      onChange={handleSheetChanges}
      backdropComponent={renderBackdrop}
      handleIndicatorStyle={{ backgroundColor: '#a1a1a1' }}
    >
      {/* ... Sheet内容 */}
    </BottomSheet>
  </View>
);

内容的提问来源于stack exchange,提问作者Julius Guevarra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 06:38:08