Takodana
Takodana

Reputation: 51

How to set different indicator colors for active and inactive tabs in Material Top Tabs Navigator 6.x of react-navigation/native?

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?

Upvotes: 0

Views: 230

Answers (2)

Surender Kumar
Surender Kumar

Reputation: 1285

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>
  );
}

Upvotes: 0

Dhyana Dave
Dhyana Dave

Reputation: 323

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;

Upvotes: 0

Related Questions