Урок 05

Drawer Navigator

Боковое меню, открывающееся свайпом или по кнопке. Как в Gmail.

Установка

npx expo install @react-navigation/drawer
npx expo install react-native-gesture-handler react-native-reanimated

Настройка babel

В babel.config.js:

module.exports = function (api) {
    api.cache(true);
    return {
        presets: ['babel-preset-expo'],
        plugins: ['react-native-reanimated/plugin'],
    };
};

react-native-reanimated/plugin — обязательно в конце списка.

Импорт в корне

// App.tsx или index.js — самое начало
import 'react-native-gesture-handler';

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

import { createDrawerNavigator } from '@react-navigation/drawer';

const Drawer = createDrawerNavigator();

export default function DrawerNavigator() {
    return (
        <Drawer.Navigator>
            <Drawer.Screen name="Home" component={HomeScreen} />
            <Drawer.Screen name="Profile" component={ProfileScreen} />
            <Drawer.Screen name="Settings" component={SettingsScreen} />
        </Drawer.Navigator>
    );
}

Кастомный drawer

<Drawer.Navigator
    drawerContent={(props) => <CustomDrawer {...props} />}
>
import { DrawerContentScrollView, DrawerItemList, DrawerItem } from '@react-navigation/drawer';

function CustomDrawer(props: DrawerContentComponentProps) {
    return (
        <DrawerContentScrollView {...props}>
            <View style={styles.header}>
                <Avatar source={{ uri: user.avatar }} />
                <Text style={styles.name}>{user.name}</Text>
                <Text style={styles.email}>{user.email}</Text>
            </View>

            <DrawerItemList {...props} />

            <DrawerItem
                label="Выйти"
                onPress={() => logout()}
                icon={({ size, color }) => <Ionicons name="log-out" size={size} color={color} />}
            />
        </DrawerContentScrollView>
    );
}

Настройки

<Drawer.Navigator
    screenOptions={{
        drawerActiveTintColor: '#c1442e',
        drawerInactiveTintColor: '#333',
        drawerActiveBackgroundColor: '#fdece8',
        drawerStyle: {
            backgroundColor: '#fff',
            width: 280,
        },
        drawerPosition: 'left', // 'left' | 'right'
        drawerType: 'front',    // 'front' | 'back' | 'slide' | 'permanent'
        swipeEnabled: true,
        swipeEdgeWidth: 50,
        headerShown: true,
    }}
>

Открыть из кода

navigation.openDrawer();
navigation.closeDrawer();
navigation.toggleDrawer();

Иконки в меню

<Drawer.Screen
    name="Home"
    component={HomeScreen}
    options={{
        drawerLabel: 'Главная',
        drawerIcon: ({ color, size }) => <Ionicons name="home" size={size} color={color} />,
    }}
/>

Бейдж

options={{
    drawerLabel: () => (
        <View style={{ flexDirection: 'row', alignItems: 'center' }}>
            <Text>Сообщения</Text>
            <Badge>3</Badge>
        </View>
    ),
}}

Связка со стеком

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

Когда использовать

  • Drawer — для больших приложений с множеством разделов
  • Tab — для 3–5 главных разделов
  • Комбинация — табы внизу, drawer для второстепенного

Итоги

  • createDrawerNavigator
  • Требует gesture-handler и reanimated
  • Кастомный drawerContent
  • openDrawer, closeDrawer, toggleDrawer
  • drawerActiveTintColor для активного