Creating a Custom Tab Bar in React Native (Archived)
Note: This tutorial was published in 2021 and uses React Navigation v5.
The React Navigation library has since released major new versions. The setup process, dependencies, and some APIs may have changed significantly. While the general concepts of customizing a tab bar are still relevant, the code examples provided here are specific to version 5. Always consult the official React Navigation documentation for the latest practices. This article is preserved for historical reference.
The React Navigation library is the standard solution for implementing navigation in React Native applications, offering patterns like stack, tab, and drawer navigators. While the default components are highly functional, many applications require a custom look and feel to match their design system.
This tutorial demonstrates how to create a custom, translucent tab bar using React Navigation's bottom tabs navigator. The process involves replacing the default tab bar component with a custom component that incorporates a BlurView for the translucent effect.
Prerequisites
To follow this tutorial, you will need:
- Node.js (version >= 12.x.x)
- A package manager such as npm or yarn
react-native-cliinstalled globally, or accessible vianpx
Installing Dependencies
First, create a new React Native project and install the necessary dependencies for React Navigation and the blur view.
npx react-native init customTabBar
cd customTabBar
# Install React Navigation and its peer dependencies
yarn add @react-navigation/native @react-navigation/bottom-tabs
yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
# Install other utilities
yarn add react-native-vector-icons @react-native-community/blur
After installing, ensure react-native-gesture-handler is imported at the top of your index.js file:
import 'react-native-gesture-handler';
For iOS, navigate to the ios directory and install the pods.
cd ios && pod install
Configuring Vector Icons
The react-native-vector-icons library requires additional setup. For iOS, add the UIAppFonts key to your ios/customTabBar/Info.plist file with the list of font files. For Android, apply the fonts gradle script in android/app/build.gradle. Refer to the library's documentation for the full setup instructions.
Creating Mock Screens
Our tab bar will navigate between three screens: Home, Browse, and Library. Create these components inside a screens/ directory.
The Home.js screen will display a scrollable list of images to demonstrate the translucency effect.
// screens/Home.js
import React from 'react';
import { View, Text, StyleSheet, Image, ScrollView } from 'react-native';
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
import { data } from './data'; // Your mock data array
const Home = () => {
const tabBarHeight = useBottomTabBarHeight();
return (
<View style={styles.container}>
<View style={styles.contentContainer}>
<Text style={styles.title}>Home</Text>
</View>
<ScrollView
contentContainerStyle={{ paddingBottom: tabBarHeight }}
>
{data.map(item => (
<View key={item.id} style={styles.imageContainer}>
<Image style={styles.imageCard} source={{ uri: item.image_url }} />
</View>
))}
</ScrollView>
</View>
);
};
// ... styles
export default Home;
The Browse.js and Library.js screens will be simple components that display their respective titles.
Creating the Tab Navigator
Create a navigation/TabNavigator/index.js file to configure the bottom tab navigator.
import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Icon from 'react-native-vector-icons/AntDesign';
import Home from '../../screens/Home';
import Browse from '../../screens/Browse';
import Library from '../../screens/Library';
const Tab = createBottomTabNavigator();
const TabNavigator = () => {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ color, size }) => {
let iconName;
if (route.name === 'Home') iconName = 'home';
else if (route.name === 'Browse') iconName = 'appstore-o';
else if (route.name === 'Library') iconName = 'folder1';
return <Icon name={iconName} size={size} color={color} />;
},
})}
tabBarOptions={{
activeTintColor: 'white',
inactiveTintColor: '#d9d9d9',
}}
>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Browse" component={Browse} />
<Tab.Screen name="Library" component={Library} />
</Tab.Navigator>
);
};
export default TabNavigator;
Wrap this TabNavigator inside a NavigationContainer in a navigation/RootNavigator.js file, and render the RootNavigator in App.js.
Creating a Custom Translucent Tab Bar
To create the custom tab bar, we will replace the default component with our own. The tabBar prop on Tab.Navigator allows you to provide a custom component to render the tab bar.
Create navigation/TabNavigator/CustomTabBar.js. This component will use BlurView from @react-native-community/blur to create the translucent effect and BottomTabBar from @react-navigation/bottom-tabs to render the actual tabs.
// navigation/TabNavigator/CustomTabBar.js
import React from 'react';
import { StyleSheet } from 'react-native';
import { BottomTabBar } from '@react-navigation/bottom-tabs';
import { BlurView } from '@react-native-community/blur';
const CustomTabBar = props => {
return (
<BlurView
style={styles.blurView}
blurType="dark"
blurAmount={10}
reducedTransparencyFallbackColor="white"
>
<BottomTabBar {...props} />
</BlurView>
);
};
const styles = StyleSheet.create({
blurView: {
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
},
});
export default CustomTabBar;
Now, update TabNavigator/index.js to use this custom component. Also, set the tab bar's style to be transparent so the BlurView is visible.
// navigation/TabNavigator/index.js
import CustomTabBar from './CustomTabBar';
// ...
const TabNavigator = () => {
return (
<Tab.Navigator
// ... screenOptions
tabBarOptions={{
activeTintColor: 'white',
inactiveTintColor: '#d9d9d9',
style: {
backgroundColor: 'transparent',
borderTopWidth: 0,
position: 'absolute',
elevation: 0, // for Android
},
}}
tabBar={props => <CustomTabBar {...props} />}
>
{/* ... Tab.Screen components */}
</Tab.Navigator>
);
};
The position: 'absolute' style on the tab bar is crucial for the content to scroll underneath it.
Because the tab bar is now absolutely positioned, content at the bottom of a scrollable screen might be obscured. To fix this, we use the useBottomTabBarHeight hook in the Home.js screen to get the height of the tab bar and apply it as paddingBottom to the ScrollView's content container. This ensures the content can be scrolled fully into view.
The final result is a custom, translucent tab bar that blurs the content scrolling behind it.
Conclusion
The React Navigation library provides a powerful and flexible API for customizing navigators. By replacing the default tabBar component with a custom implementation, you can achieve unique designs, such as the translucent blur effect demonstrated in this tutorial. This component-based approach to configuration is a key strength of React Navigation v5 and newer versions.