You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何让React Navigation抽屉从底部弹出而非左右侧滑?

解决从底部滑入的React Navigation抽屉导航问题

我来帮你搞定这个底部滑入的抽屉!你的思路方向是对的,但有几个关键细节没处理到位,导致动画没生效。咱们一步步来修正:

1. 修正Props传递错误

你代码里的DrawerContentScrollView用了{...props},但函数参数接收的是{progress, ...rest},这里应该把props换成rest,不然组件拿不到正确的导航相关属性,这是个容易忽略的小bug。

2. 调整抽屉的基础布局

默认的抽屉导航是左右滑动的,所以首先得把抽屉容器定位到屏幕底部,让它初始状态在可视区域外。你需要在Drawer.NavigatordrawerStyle里设置基础样式:

drawerStyle: {
  position: 'absolute',
  bottom: 0,
  left: 0,
  right: 0,
  height: '80%', // 你可以自定义抽屉高度,比如设为'70%'或者固定数值
  backgroundColor: '#fff',
}

3. 修正动画的插值范围

你原来的outputRange: [-100, 0]数值太小,而且方向反了——抽屉要从底部滑入,初始状态应该是完全在屏幕下方(translateY等于抽屉的高度),打开时translateY变为0。我们可以用屏幕高度来动态计算这个值:

const translateY = Animated.interpolate(progress, {
  inputRange: [0, 1],
  // 0对应抽屉关闭(在屏幕外),1对应抽屉打开(完全显示)
  outputRange: [Dimensions.get('window').height * 0.8, 0],
});

完整的可运行代码示例

把这些修正整合起来,完整代码如下:

import { Dimensions, Animated } from 'react-native';
import { createDrawerNavigator } from '@react-navigation/drawer';
import { DrawerContentScrollView, DrawerItemList } from '@react-navigation/drawer';

const Drawer = createDrawerNavigator();

function CustomDrawerContent({ progress, ...rest }) {
  const windowHeight = Dimensions.get('window').height;
  // 抽屉高度设为屏幕的80%,和drawerStyle里的height对应
  const drawerHeight = windowHeight * 0.8;

  const translateY = Animated.interpolate(progress, {
    inputRange: [0, 1],
    outputRange: [drawerHeight, 0],
  });

  return (
    <Animated.View style={{ transform: [{ translateY }], flex: 1 }}>
      <DrawerContentScrollView {...rest}>
        <DrawerItemList {...rest} />
        {/* 这里可以添加你的自定义抽屉内容,比如头像、按钮等 */}
      </DrawerContentScrollView>
    </Animated.View>
  );
}

// 在导航器中使用自定义抽屉
function MyDrawer() {
  return (
    <Drawer.Navigator
      drawerContent={(props) => <CustomDrawerContent {...props} />}
      drawerStyle={{
        position: 'absolute',
        bottom: 0,
        left: 0,
        right: 0,
        height: '80%',
        backgroundColor: '#f8f8f8',
        borderTopLeftRadius: 16,
        borderTopRightRadius: 16, // 可选:给抽屉顶部加圆角,视觉效果更好
      }}
      // 可选:关闭默认的左右滑动手势,避免和底部滑入逻辑冲突
      drawerType="front"
    >
      {/* 这里添加你的屏幕组件 */}
      {/* <Drawer.Screen name="Home" component={HomeScreen} /> */}
    </Drawer.Navigator>
  );
}

额外优化建议

  • 如果想要更自然的遮罩效果,可以给背景遮罩也加上动画,比如通过progress控制遮罩的透明度:
const opacity = Animated.interpolate(progress, {
  inputRange: [0, 1],
  outputRange: [0, 0.5],
});
// 然后在自定义抽屉外层添加遮罩视图
<Animated.View style={{ flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', opacity }}>
  {/* 抽屉内容 */}
</Animated.View>

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

火山引擎 最新活动