Turn the Tab navigation reactnavigation.org/docs/tab-ba… Translation RecoReco

Probably the most common navigation style in mobile applications is tag-based navigation. This can be a TAB at the bottom of the screen or a top TAB at the bottom of the header (or even in place of the header).

This guide describes the createBottomTabNavigator. You can also use createMaterialBottomTabNavigator and createMaterialTopTabNavigator to add tags for your application.

Before continuing, install @react-navigation/bottom-tabs.

npm install @react-navigation/bottom-tabs
Copy the code

Example of minimal tag-based navigation

import * as React from 'react'; import { Text, View } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; 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> ); } const Tab = createBottomTabNavigator(); export default function App() { return ( <NavigationContainer> <Tab.Navigator> <Tab.Screen name="Home" component={HomeScreen} /> <Tab.Screen name="Settings" component={SettingsScreen} /> </Tab.Navigator> </NavigationContainer> ); }Copy the code

Custom appearance

This is similar to how you customize the stack navigator — some properties are set when initializing the TAB navigator, and some properties can be customized by screen in options.

import Ionicons from 'react-native-vector-icons/Ionicons'; import * as React from 'react'; import { Text, View } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; 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> ); } const Tab = createBottomTabNavigator(); export default function App() { return ( <NavigationContainer> <Tab.Navigator screenOptions={({ route }) => ({ tabBarIcon: ({ focused, color, size }) => { let iconName; if (route.name === 'Home') { iconName = focused ? 'ios-information-circle' : 'ios-information-circle-outline'; } else if (route.name === 'Settings') { iconName = focused ? 'ios-list-box' : 'ios-list'; } // You can return any component that you like here! return <Ionicons name={iconName} size={size} color={color} />; }, })} tabBarOptions={{ activeTintColor: 'tomato', inactiveTintColor: 'gray', }} > <Tab.Screen name="Home" component={HomeScreen} /> <Tab.Screen name="Settings" component={SettingsScreen} /> </Tab.Navigator> </NavigationContainer> ); }Copy the code

Let’s dissect it.

TabBarIcon is an option supported in the bottom TAB navigator. So we knew we could use it in the properties of our screen component, but in this case we chose to put it in the screenOptions property of the Tab.Navigator to centrally configure the icon for easy use.

TabBarIcon is a function given the focus state, color, and size parameters. If you look further down in configuration, you’ll see tabBarOptions and activeTintColor and inactiveTintColor. These are the default values for iOS, but you can change them here. The colors passed to tabBarIcon are active or inactive colors. The size is the desired icon size for the TAB bar.

Read the full API Reference to learn more about the createBottomTabNavigator configuration option.

## Add badges to ICONS

Sometimes we want to add badges to some ICONS. A common approach is to use an extra view container and style the badge element with absolute positioning.

  import * as React from 'react';
  import { Text, View } from 'react-native';
  import { Ionicons } from '@expo/vector-icons';
  import { NavigationContainer } from '@react-navigation/native';
  import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
  function IconWithBadge({ name, badgeCount, color, size }) {
    return (
      <View style={{ width: 24, height: 24, margin: 5 }}>
        <Ionicons name={name} size={size} color={color} />
        {badgeCount > 0 && (
          <View
            style={{
              // On React Native < 0.57 overflow outside of parent will not work on Android, see https://git.io/fhLJ8
              position: 'absolute',
              right: -6,
              top: -3,
              backgroundColor: 'red',
              borderRadius: 6,
              width: 12,
              height: 12,
              justifyContent: 'center',
              alignItems: 'center',
            }}
          >
            <Text style={{ color: 'white', fontSize: 10, fontWeight: 'bold' }}>
              {badgeCount}
            </Text>
          </View>
        )}
      </View>
    );
  }
  function HomeIconWithBadge(props) {
    // You should pass down the badgeCount in some other ways like React Context API, Redux, MobX or event emitters.
    return <IconWithBadge {...props} badgeCount={3} />;
  }
  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>
    );
  }
  const Tab = createBottomTabNavigator();
  export default function App() {
    return (
      <NavigationContainer>
        <Tab.Navigator
          screenOptions={({ route }) => ({
            tabBarIcon: ({ focused, color, size }) => {
              if (route.name === 'Home') {
                return (
                  <HomeIconWithBadge
                    name={
                      focused
                        ? 'ios-information-circle'
                        : 'ios-information-circle-outline'
                    }
                    size={size}
                    color={color}
                  />
                );
              } else if (route.name === 'Settings') {
                return (
                  <Ionicons
                    name={focused ? 'ios-list-box' : 'ios-list'}
                    size={size}
                    color={color}
                  />
                );
              }
            },
          })}
          tabBarOptions={{
            activeTintColor: 'tomato',
            inactiveTintColor: 'gray',
          }}
        >
          <Tab.Screen name="Home" component={HomeScreen} />
          <Tab.Screen name="Settings" component={SettingsScreen} />
        </Tab.Navigator>
      </NavigationContainer>
    );
  }
Copy the code

Jump between labels

Switching from one label to another has a familiar API – navigation.navigate.

function HomeScreen({ navigation }) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home! </Text> <Button title="Go to Settings" onPress={() => navigation.navigate('Settings')} /> </View> ); } function SettingsScreen({ navigation }) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Settings! </Text> <Button title="Go to Home" onPress={() => navigation.navigate('Home')} /> </View> ); }Copy the code

Stack navigator for each tag

Often tabs don’t just show one screen — on your Twitter feed, for example, you can click on a tweet and it will take you to a new screen within that TAB with all the replies. You can think of it as a separate Navigation stack for each TAB, which is exactly how we modeled React Navigation.

import * as React from 'react'; import { Button, Text, View } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; function DetailsScreen() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Details! </Text> </View> ); } function HomeScreen({ navigation }) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home screen</Text> <Button title="Go to Details" onPress={() => navigation.navigate('Details')} /> </View> ); } function SettingsScreen({ navigation }) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Settings screen</Text> <Button title="Go to Details" onPress={() => navigation.navigate('Details')} /> </View> ); } const HomeStack = createStackNavigator(); function HomeStackScreen() { return ( <HomeStack.Navigator> <HomeStack.Screen name="Home" component={HomeScreen} /> <HomeStack.Screen name="Details" component={DetailsScreen} /> </HomeStack.Navigator> ); } const SettingsStack = createStackNavigator(); function SettingsStackScreen() { return ( <SettingsStack.Navigator> <SettingsStack.Screen name="Settings" component={SettingsScreen} /> <SettingsStack.Screen name="Details" component={DetailsScreen} /> </SettingsStack.Navigator> ); } const Tab = createBottomTabNavigator(); export default function App() { return ( <NavigationContainer> <Tab.Navigator> <Tab.Screen name="Home" component={HomeStackScreen} /> <Tab.Screen name="Settings" component={SettingsStackScreen} /> </Tab.Navigator> </NavigationContainer> ); }Copy the code

Why do we need TabNavigator and not TabBarIOS or some other component?

It is common to try to use a separate TAB bar component without integrating it into the navigation library used in your application. In some cases, this is fine! When doing so, however, you may encounter some frustrating unexpected problems.

For example, the React Navigation TAB navigator handles the Android back button for you, whereas standalone components typically don’t. Also, if you need to call two different apis for it, it’s harder for you (as a developer) to do things like “go to this TAB, then go to this screen”.

Finally, the design of the mobile user interface, there are many small details, request some components can realize the layout of the other components or exist, for example, if you have a translucent tabs, content should be below it rolling, rolling view should have a label on the bottom column height is equal to inset, so you can see all of the content. Double-clicking the TAB bar should cause the active navigation stack to pop to the top of the stack, and doing so again should cause the active scroll view in that stack to scroll to the top. While these behaviors are not all out of the box yet in React Navigation, they will be implemented and you won’t get any of these if you use a separate TAB view component.