Урок 04

Bottom Tab Navigator

Нижние вкладки — стандарт для главных экранов приложения. Как в Instagram, ВК, Telegram.

Установка

npx expo install @react-navigation/bottom-tabs

Базовое использование

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const Tab = createBottomTabNavigator();

export default function TabNavigator() {
    return (
        <Tab.Navigator>
            <Tab.Screen name="Feed" component={FeedScreen} />
            <Tab.Screen name="Search" component={SearchScreen} />
            <Tab.Screen name="Profile" component={ProfileScreen} />
        </Tab.Navigator>
    );
}

Иконки

<Tab.Navigator
    screenOptions={({ route }) => ({
        tabBarIcon: ({ focused, color, size }) => {
            const icons = {
                Feed: focused ? 'home' : 'home-outline',
                Search: focused ? 'search' : 'search-outline',
                Profile: focused ? 'person' : 'person-outline',
            };
            return <Ionicons name={icons[route.name]} size={size} color={color} />;
        },
        tabBarActiveTintColor: '#c1442e',
        tabBarInactiveTintColor: '#999',
    })}
>

С заголовком

<Tab.Screen
    name="Feed"
    component={FeedScreen}
    options={{
        tabBarLabel: 'Лента',
        title: 'Лента',
        tabBarBadge: 3,
    }}
/>

tabBarBadge — красный кружок с числом.

Типизация

type TabParamList = {
    Feed: undefined;
    Search: undefined;
    Profile: { userId?: string };
};

const Tab = createBottomTabNavigator<TabParamList>();

Скрыть таббар на экране

<Tab.Screen
    name="Chat"
    component={ChatScreen}
    options={{ tabBarStyle: { display: 'none' } }}
/>

Или в компоненте:

useLayoutEffect(() => {
    navigation.getParent()?.setOptions({ tabBarStyle: { display: 'none' } });
    return () => navigation.getParent()?.setOptions({ tabBarStyle: undefined });
}, [navigation]);

Кастомный таббар

<Tab.Navigator tabBar={(props) => <CustomTabBar {...props} />}>

Настройки таббара

screenOptions={{
    tabBarActiveTintColor: '#c1442e',
    tabBarInactiveTintColor: '#999',
    tabBarStyle: {
        backgroundColor: '#fff',
        borderTopColor: '#e5e5e5',
        height: 60,
        paddingBottom: 8,
        paddingTop: 8,
    },
    tabBarLabelStyle: {
        fontSize: 12,
        fontWeight: '600',
    },
    tabBarHideOnKeyboard: true,
    headerShown: true,
}}

Табы в связке со стеком

Обычно стек оборачивает табы:

function RootNavigator() {
    return (
        <Stack.Navigator screenOptions={{ headerShown: false }}>
            <Stack.Screen name="Tabs" component={TabNavigator} />
            <Stack.Screen name="Details" component={DetailsScreen} />
            <Stack.Screen name="Settings" component={SettingsScreen} />
        </Stack.Navigator>
    );
}

Таббар показывается на главных экранах. При переходе в Details — таббар скрывается (потому что это стек).

Дочерняя навигация

Из таба перейти в стек:

function FeedScreen() {
    const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();

    return (
        <Pressable onPress={() => navigation.navigate('Details', { id: 5 })}>
            <Text>Открыть</Text>
        </Pressable>
    );
}

useNavigation автоматически возвращает родительский стек.

Итоги

  • createBottomTabNavigator
  • tabBarIcon с иконками
  • tabBarActiveTintColor для активного
  • tabBarBadge для уведомлений
  • Стек оборачивает табы
  • tabBarHideOnKeyboard для клавиатуры