skip to Main Content

I’m using Material Top Tabs Navigator from React Navigation. Here’s an example:

import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';

const Tab = createMaterialTopTabNavigator();

function MyTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Chat" component={ChatScreen} />
      <Tab.Screen name="Contacts" component={ContactsScreen} />
      <Tab.Screen name="Albums" component={AlbumsScreen} />
    </Tab.Navigator>
  );
}

By default, tab indicator is displayed only for the active tab like the following:
enter image description here

However I want inactive tabs to have tab indicators as well. These inactive tabs indicators should be a different color like below:

enter image description here

I can change default indicator color for active tab by adding tabBarIndicatorStyle option to navigator:

<Tab.Navigator
  screenOptions={{ tabBarIndicatorStyle: { backgroundColor: colors.white } }}
>
    <Tab.Screen name="Chat" component={ChatScreen} />
    <Tab.Screen name="Contacts" component={ContactsScreen} />
    <Tab.Screen name="Albums" component={AlbumsScreen} />
</Tab.Navigator>

But how to set indicator color for inactive tabs?

2

Answers


  1. To set the style of the indicator under the inactive tab, you need to use a custom tab bar component because the default createMaterialTopTabNavigator does not support directly styling the indicator for inactive tabs. You can achieve this by customizing the tab bar’s rendering.

    Here’s an example of how you can create a custom tab bar component to style the indicator under the inactive tabs:

    import React from 'react';
    import { View, Text, TouchableOpacity } from 'react-native';
    
    function CustomTabBar({ state, descriptors, navigation, position }) {
      return (
        <View style={{ flexDirection: 'row', backgroundColor: 'white' }}>
          {state.routes.map((route, index) => {
            const { options } = descriptors[route.key];
            const label =
              options.tabBarLabel !== undefined
                ? options.tabBarLabel
                : options.title !== undefined
                ? options.title
                : route.name;
    
            const isFocused = state.index === index;
    
            const onPress = () => {
              const event = navigation.emit({
                type: 'tabPress',
                target: route.key,
                canPreventDefault: true,
              });
    
              if (!isFocused && !event.defaultPrevented) {
                navigation.navigate(route.name);
              }
            };
    
            const onLongPress = () => {
              navigation.emit({
                type: 'tabLongPress',
                target: route.key,
              });
            };
    
            return (
              <TouchableOpacity
                key={route.key}
                accessibilityRole="button"
                accessibilityState={isFocused ? { selected: true } : {}}
                accessibilityLabel={options.tabBarAccessibilityLabel}
                testID={options.tabBarTestID}
                onPress={onPress}
                onLongPress={onLongPress}
                style={{ flex: 1, alignItems: 'center', padding: 10 }}
              >
                <Text style={{ color: isFocused ? 'blue' : 'gray' }}>
                  {label}
                </Text>
                <View
                  style={{
                    height: 2,
                    backgroundColor: isFocused ? 'blue' : 'gray',
                    marginTop: 4,
                    width: '100%',
                  }}
                />
              </TouchableOpacity>
            );
          })}
        </View>
      );
    }
    
    export default CustomTabBar;
    

    you can use custom tab bar like this:

    import React from 'react';
    import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
    import ChatScreen from './ChatScreen';
    import ContactsScreen from './ContactsScreen';
    import AlbumsScreen from './AlbumsScreen';
    import CustomTabBar from './CustomTabBar'; // Import the custom tab bar
    
    const Tab = createMaterialTopTabNavigator();
    
    function MyTabs() {
      return (
        <Tab.Navigator tabBar={props => <CustomTabBar {...props} />}>
          <Tab.Screen name="Chat" component={ChatScreen} />
          <Tab.Screen name="Contacts" component={ContactsScreen} />
          <Tab.Screen name="Albums" component={AlbumsScreen} />
        </Tab.Navigator>
      );
    }
    
    export default MyTabs;
    
    Login or Signup to reply.
  2. In @react-navigation/material-top-tabs, there isn’t a direct prop for setting the inactive indicator color.

    To achieve different styles for active and inactive tab indicators, you would need a custom tab bar component. Here’s how you can create a custom tab bar to handle different indicator colors for active and inactive tabs:

    yarn add react-native-tab-view
    

    Create a custom tab bar component:

    import * as React from 'react';
    import { View, useWindowDimensions } from 'react-native';
    import { NavigationContainer } from '@react-navigation/native';
    import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
    import { TabBar, TabView } from 'react-native-tab-view';
    
    const Tab = createMaterialTopTabNavigator();
    
    function HomeScreen() {
      return <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Home</Text></View>;
    }
    
    function SettingsScreen() {
      return <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Settings</Text></View>;
    }
    
    function CustomTabBar(props) {
      const { state, navigation, position } = props;
      const { width } = useWindowDimensions();
    
      return (
        <TabBar
          {...props}
          indicatorStyle={{ backgroundColor: 'blue' }} // Active indicator color
          renderIndicator={({ route }) => {
            const isFocused = state.index === state.routes.indexOf(route);
            return (
              <View
                style={{
                  backgroundColor: isFocused ? 'blue' : 'gray', // Active and inactive indicator colors
                  height: 4,
                  width: width / state.routes.length,
                }}
              />
            );
          }}
        />
      );
    }
    
    export default function App() {
      return (
        <NavigationContainer>
          <Tab.Navigator
            tabBar={(props) => <CustomTabBar {...props} />}
            screenOptions={{
              tabBarActiveTintColor: 'blue',    // Color of the active tab text
              tabBarInactiveTintColor: 'gray',  // Color of the inactive tab text
            }}
          >
            <Tab.Screen name="Home" component={HomeScreen} />
            <Tab.Screen name="Settings" component={SettingsScreen} />
          </Tab.Navigator>
        </NavigationContainer>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search