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

React Native Android端@gorhom/bottom-sheet无法关闭等异常问题

Android端@gorhom/bottom-sheet底部弹窗异常排查与解决

问题现象

使用@gorhom/bottom-sheet开发的底部弹窗,仅在Android设备上出现以下异常:

  • 弹窗无法通过滑动或点击backdrop关闭,上下滑动手势完全失效
  • 键盘弹出时,弹窗背景保持透明状态

组件代码

const BottomSheetComponent = (props: BottomSheetComponentProps, ref) => {
  const theme = useCustomTheme();
  const styles = useMemo(() => makeStyles(theme), [theme]);

  const {children, visible, onClose, header, snapPoints = ['70%', '70%'], enablePanDownToClose = true, renderBackdrop = true } = props;

  // const bottomSheetRef = useRef<BottomSheet>(null);
  const detached = true;

  /**
   * onClick outside to close bottomsheet
   */
  const renderBackdropComponent = useCallback(
    props => <BottomSheetBackdrop {...props} />,
    [],
  );

  return (
    <Modal visible={visible} transparent>
      <BottomSheet
        ref={ref}
        onClose={onClose}
        backdropComponent={renderBackdrop ? renderBackdropComponent : null}
        snapPoints={snapPoints}
        detached={detached}
        enablePanDownToClose={enablePanDownToClose}
        keyboardBehavior={'interactive'}
        keyboardBlurBehavior={'restore'}
        style={styles.container}
        handleStyle={styles.handleStyle}
        handleIndicatorStyle={styles.indicatorStyle}
      >
        <View style={styles.contentContainer}>
          {header}
          {children}
        </View>
      </BottomSheet>
    </Modal>
  );
};

export default forwardRef(BottomSheetComponent);

样式代码

const makeStyles = (theme: ColorTheme) => StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: theme.primaryDark,
    shadowColor: theme.white,
    shadowOffset: {
      width: 0,
      height: 12
    },
    shadowOpacity: 0.5,
    shadowRadius: 16,
    elevation: 24
  },
  handleStyle: {
    backgroundColor: theme.primaryDark,
    // borderTopColor: theme.backgroundGrey,
  },
  indicatorStyle: {
    backgroundColor: theme.secondaryGrey,
    width: scaleWidth(56),
  },
  contentContainer: {
    flex: 1,
    backgroundColor: theme.primaryDark,
  },
});

已尝试方案

  • 调整手势处理相关配置参数
  • 重新安装react-native-gesture-handler库
    问题未得到解决

针对性解决方法

1. 移除外层嵌套的官方Modal

@gorhom/bottom-sheet自身已经集成了Modal功能,外层再套<Modal>会导致Android端手势冲突和层级混乱,这是核心问题之一。直接去掉外层Modal,改用bottom-sheet自带的visible属性控制显示:

修改后的返回部分代码:

return (
  <BottomSheet
    ref={ref}
    visible={visible}
    onClose={onClose}
    backdropComponent={renderBackdrop ? renderBackdropComponent : null}
    snapPoints={snapPoints}
    detached={detached}
    enablePanDownToClose={enablePanDownToClose}
    keyboardBehavior={'interactive'}
    keyboardBlurBehavior={'restore'}
    style={styles.container}
    handleStyle={styles.handleStyle}
    handleIndicatorStyle={styles.indicatorStyle}
  >
    <View style={styles.contentContainer}>
      {header}
      {children}
    </View>
  </BottomSheet>
);

2. 修正detached属性设置

detached={true}在Android平台会干扰手势识别区域,建议根据平台动态设置:

import { Platform } from 'react-native';

const detached = Platform.OS !== 'android';

或者直接设置为false,测试手势是否恢复正常。

3. 修复键盘弹出时背景透明问题

给Backdrop组件添加明确的半透明背景色,避免键盘弹出时背景层级异常:

const renderBackdropComponent = useCallback(
  props => <BottomSheetBackdrop {...props} style={{ backgroundColor: 'rgba(0, 0, 0, 0.6)' }} />,
  [],
);

同时确保bottom-sheet的container和contentContainer样式中的backgroundColor已正确赋值,不会继承透明属性。

4. 调整snapPoints配置

当前snapPoints = ['70%', '70%']设置了两个相同的阈值,会导致滑动逻辑失效,改为合理的数组:

const {..., snapPoints = ['70%'], ...} = props;

或者设置多个不同的阈值,比如['50%', '70%'],让滑动有明确的目标位置。

5. 检查手势库Android配置

确认react-native-gesture-handler在Android项目中的配置正确:

  • 打开android/app/src/main/java/[你的包名]/MainActivity.java
  • 添加导入:import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
  • 重写createRootView方法:
@Override
protected ReactRootView createRootView() {
  return new RNGestureHandlerEnabledRootView(this);
}

内容的提问来源于stack exchange,提问作者Kumar Shivam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:45:45