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

react-navigation自定义DrawerNavigator:如何设置DrawerItem激活/非激活背景色

自定义DrawerItem激活/非激活样式的实现方案

样式不生效的核心原因

  • API版本不兼容:从@react-navigation/drawer v6版本开始,旧的drawerContentOptions配置项已被完全废弃移除,无法对组件产生任何配置作用,原有的activeTintColor、activeBackgroundColor等参数已迁移到screenOptions的drawer前缀配置项中。
  • 自定义组件的传参逻辑错误:你的CustomDrawerContent组件写法function CustomDrawerContent({ props, navigation })存在解构错误——父组件传递的整个对象本身就是抽屉渲染所需的props(包含navigation、路由状态、默认样式配置等),不存在嵌套的props属性,导致后续给DrawerItem传递{...props}时根本拿不到有效状态数据。
  • 动态渲染的条目无内置激活判断:你基于redux中的outlet数据循环渲染的DrawerItem不属于与Drawer.Screen绑定的系统路由项,不会自动携带isFocused激活状态,就算配置了全局样式,系统也无法识别哪个条目应该应用激活样式。

分步实现自定义样式

1. 全局配置默认抽屉样式(替代旧的drawerContentOptions)

将原来写在drawerContentOptions里的配置迁移到Drawer.Navigator的screenOptions中,作为所有绑定路由的DrawerItem的默认样式:

<Drawer.Navigator
  // 替代旧drawerContentOptions的全局样式配置
  screenOptions={{
    drawerActiveTintColor: '#fff', // 激活状态文字色
    drawerActiveBackgroundColor: '#68f', // 激活状态背景色
    drawerInactiveTintColor: 'grey', // 非激活状态文字色
    drawerInactiveBackgroundColor: 'transparent' // 非激活状态背景
  }}
  drawerContent={(props) => <CustomDrawerContent {...props} />}
  initialRouteName="Home"
>
  <Drawer.Screen name="Home" component={Home} />
</Drawer.Navigator>

2. 修正自定义抽屉组件的逻辑错误

  • 修正组件的props接收方式,不再错误嵌套解构props属性
  • 针对动态渲染的outlet条目,结合redux中存储的选中状态手动判断激活态,绑定对应样式

修正后的CustomDrawerContent核心逻辑:

// 错误写法修正:直接接收props对象,不再嵌套解构props属性
function CustomDrawerContent(props) {
  const dispatch = useDispatch();
  const navigation = props.navigation;
  const outlets = useSelector((state) => state.homeReducer.outlets);
  const defaultOutLet = useSelector((state) => state.homeReducer.defaultOutLet);

  const drawerItems = outlets.map((outlet) => {
    // 手动判断当前条目是否为激活状态
    const isItemActive = defaultOutLet?.userCompanyId === outlet.userCompanyId;
    return (
      <DrawerItem
        key={outlet.userCompanyId}
        label={outlet.name}
        // 手动绑定激活/非激活样式
        labelStyle={{
          color: isItemActive ? '#fff' : 'grey'
        }}
        style={{
          backgroundColor: isItemActive ? '#68f' : 'transparent'
        }}
        onPress={() => {
          dispatch(homeActions.changeSelectedOutlet(outlet));
          navigation.closeDrawer();
        }}
      />
    );
  });

  // 原有头部、分割线、退出按钮的UI逻辑保持不变
  return (
    <View style={styles.flexView}>
      <View style={styles.container}>
        <Image
          style={styles.image}
          source={Images.icons.logo}
          resizeMode="contain"
        />
        {defaultOutLet && <Text style={styles.text}>{defaultOutLet.name}</Text>}
      </View>
      <View style={styles.separator} />
      <View style={styles.flexView}>{drawerItems}</View>
      <View style={styles.separator} />
      <View style={styles.bottomView}>
        <TouchableOpacity
          style={styles.logoutContainer}
          onPress={() => {
            dispatch(homeActions.clearUserCompany());
            dispatch(loginActions.completeLogOutClearingUserData());
          }}>
          <Image
            style={styles.logoutIcon}
            source={Images.icons.power}
            resizeMode="center"
          />
          <Text style={styles.logoutText}>{i18n.t('common.logout')}</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
}

3. 关键注意事项

  • 不要给动态渲染的非路由类DrawerItem传递{...props},这些props是系统为自动生成的路由条目准备的状态数据,强行传递可能导致样式错乱、状态判断异常。
  • 如果你需要保留系统自动识别的路由激活态(比如绑定Drawer.Screen的Home、Notifications页面),不要拦截props的正常传递,系统会自动根据当前路由的聚焦状态应用全局配置的激活/非激活样式。
  • 对于所有非路由类的自定义条目(比如你的outlet列表),必须手动维护激活态的判断逻辑,系统不会自动为这类条目匹配激活样式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 12:15:08