react-nativestylesreact-native-navigationreact-navigation-top-tabs

How to adjust material top tabs width individually in react native


WhatsApp UI

My goal is to copy WhatsApp UI. However, I am having trouble making the camera icon smaller while keeping the others flexed in the row direction. Below is code

<Tab.Navigator
  screenOptions={{
    tabBarPosition: 'top',
    tabBarIndicatorStyle: {
      backgroundColor: colors.text,
      height: 4,
    },
    tabBarStyle: {
      backgroundColor: colors.foreground,
    },
    tabBarContentContainerStyle: {
      flexDirection: 'row',
      flex: 1,
      justifyContent: 'space-between',
      // alignItems: 'center',
    },
    tabBarLabelStyle: {
      fontWeight: '600',
    },
    tabBarActiveTintColor: colors.text,
    tabBarInactiveTintColor: colors.secondaryText,
  }}
  initialRouteName="chats">
  <Tab.Screen
    name="Camera"
    component={Camera}
    options={{
      tabBarIcon: ({ color }) => (
        <AntDesign name="camera" size={24} color={color} />
      ),
      tabBarLabel: () => null,
      tabBarItemStyle: { width: 50 },
      tabBarIconStyle: { width: 75 },
    }}
  />
  <Tab.Screen
    name="Chats"
    component={Chats}
  />
  <Tab.Screen
    name="Status"
    component={Status}
  />
  <Tab.Screen
    name="Calls"
    component={Calls}
  />
</Tab.Navigator>

After messing around with the width of tabBarItemStyle, I noticed that on click, it changes other tabs widths as well. In the documentation for tabBarItemStyle, it says it changes the individual styling, but it is not what I am experiencing. I get the following when I click the camera icon:

my whatsapp ui

and when I click other tabs this:

this

I can't change the style of the tab individually, I tried lots of different variations. What am I missing? Thanks in advance.


Solution

  • I can reproduce the same issue. It seems that tabBarItemStyle is shared across all tab items. That's probably due to the limitation of the default tab bar component.

    Perhaps in the documentation, Style object for the individual tab items can be interpreted as for each tab item

    The best way I can think of is to keep the item style the same, set the tabBarLabelStyle individually.

      <Tab.Screen
        name="Camera"
        component={Camera}
        options={{
          tabBarIcon: ({ color }) => (
            <AntDesign name="camera" size={24} color={color} />
          ),
          tabBarLabel: () => null,
          // use margin to move the icon
          tabBarIconStyle: { marginRight: '60%', width: 50 },
          tabBarIndicatorStyle: { width: 50 }
        }}
      />
      <Tab.Screen
        name="Chats"
        component={Chats}
      />
      <Tab.Screen
        name="Status"
        component={Status}
      />
      <Tab.Screen
        name="Calls"
        component={Calls}
      />
    

    Result when camera is active

    Caveat:

    Otherwise creating a custom tab bar can give the best result, as mentioned in the comment.