Kurs React Native · Moduł 3: Nawigacja

Drawer Navigation - Boczne Menu Pałacu

3 min czytania ·
W tej lekcji7

Drawer Navigation to wysuwane boczne menu, idealne dla aplikacji z wieloma sekcjami lub ustawieniami.

Instalacja

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

Konfiguracja babel.config.js

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

Podstawowy Drawer

import { createDrawerNavigator } from '@react-navigation/drawer';
import { Ionicons } from '@expo/vector-icons';

type DrawerParamList = {
  Home: undefined;
  Profile: undefined;
  Settings: undefined;
  Help: undefined;
};

const Drawer = createDrawerNavigator<DrawerParamList>();

function App() {
  return (
    <NavigationContainer>
      <Drawer.Navigator
        screenOptions={{
          drawerStyle: {
            backgroundColor: '#0a2e4a',
            width: 280,
          },
          drawerActiveTintColor: '#00d4ff',
          drawerInactiveTintColor: '#a0aec0',
          drawerLabelStyle: {
            marginLeft: -20,
            fontSize: 16,
          },
          headerStyle: {
            backgroundColor: '#0a2e4a',
          },
          headerTintColor: '#fff',
        }}
      >
        <Drawer.Screen
          name="Home"
          component={HomeScreen}
          options={{
            drawerIcon: ({ color, size }) => (
              <Ionicons name="home" size={size} color={color} />
            ),
            drawerLabel: 'Strona główna',
          }}
        />
        <Drawer.Screen
          name="Profile"
          component={ProfileScreen}
          options={{
            drawerIcon: ({ color, size }) => (
              <Ionicons name="person" size={size} color={color} />
            ),
          }}
        />
        <Drawer.Screen
          name="Settings"
          component={SettingsScreen}
          options={{
            drawerIcon: ({ color, size }) => (
              <Ionicons name="settings" size={size} color={color} />
            ),
          }}
        />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}

Niestandardowa zawartość Drawer

import {
  DrawerContentScrollView,
  DrawerItemList,
  DrawerItem
} from '@react-navigation/drawer';

function CustomDrawerContent(props: DrawerContentComponentProps) {
  const { navigation } = props;

  return (
    <DrawerContentScrollView {...props}>
      {/* Nagłówek z profilem użytkownika */}
      <View style={styles.drawerHeader}>
        <Image
          source={{ uri: 'https://example.com/avatar.jpg' }}
          style={styles.avatar}
        />
        <Text style={styles.username}>Posejdon</Text>
        <Text style={styles.email}>posejdon@atlantyda.sea</Text>
      </View>

      {/* Separator */}
      <View style={styles.separator} />

      {/* Domyślna lista ekranów */}
      <DrawerItemList {...props} />

      {/* Separator */}
      <View style={styles.separator} />

      {/* Dodatkowe elementy */}
      <DrawerItem
        label="Pomoc"
        icon={({ color, size }) => (
          <Ionicons name="help-circle" size={size} color={color} />
        )}
        onPress={() => {
          // Własna akcja
          alert('Centrum pomocy Atlantydy');
        }}
      />

      <DrawerItem
        label="Wyloguj"
        icon={({ color, size }) => (
          <Ionicons name="log-out" size={size} color={color} />
        )}
        onPress={() => {
          // Logika wylogowania
          navigation.closeDrawer();
        }}
      />
    </DrawerContentScrollView>
  );
}

// Użycie
<Drawer.Navigator
  drawerContent={(props) => <CustomDrawerContent {...props} />}
>
  {/* Screens */}
</Drawer.Navigator>

Otwieranie/zamykanie Drawer programowo

import { useNavigation, DrawerActions } from '@react-navigation/native';

function HomeScreen() {
  const navigation = useNavigation();

  return (
    <View>
      <Pressable onPress={() => navigation.dispatch(DrawerActions.openDrawer())}>
        <Text>Otwórz menu</Text>
      </Pressable>

      <Pressable onPress={() => navigation.dispatch(DrawerActions.closeDrawer())}>
        <Text>Zamknij menu</Text>
      </Pressable>

      <Pressable onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}>
        <Text>Przełącz menu</Text>
      </Pressable>
    </View>
  );
}

Drawer z prawej strony

<Drawer.Navigator
  screenOptions={{
    drawerPosition: 'right', // Domyślnie 'left'
  }}
>
  {/* Screens */}
</Drawer.Navigator>

Zagnieżdżanie nawigatorów

function MainStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="MainTabs"
        component={MainTabs}
        options={{ headerShown: false }}
      />
      <Stack.Screen name="Details" component={DetailsScreen} />
    </Stack.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <Drawer.Navigator>
        <Drawer.Screen
          name="Main"
          component={MainStack}
          options={{ headerShown: false }}
        />
        <Drawer.Screen name="Settings" component={SettingsScreen} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}

Drawer Navigation świetnie sprawdza się w aplikacjach z wieloma sekcjami, panelach administracyjnych i aplikacjach korporacyjnych.

Kod do tej lekcji: App.tsx
import React from 'react';
import { View, Text, Image, StyleSheet } from 'react-native';
import {
  DrawerContentScrollView,
  DrawerItemList,
} from '@react-navigation/drawer';

// Niestandardowa zawartość szuflady (Drawer) z nagłówkiem profilu
function CustomDrawerContent(props) {
  return (
    <DrawerContentScrollView {...props}>
      {/* TODO: dodaj nagłówek profilu w <View style={styles.header}>:
          - <Image style={styles.avatar} source={{ uri: 'https://i.pravatar.cc/100' }} />
          - <Text style={styles.name}>Posejdon</Text> */}

      {/* TODO: poniżej nagłówka wyrenderuj domyślną listę pozycji: <DrawerItemList {...props} /> */}

    </DrawerContentScrollView>
  );
}

const styles = StyleSheet.create({
  header: {
    padding: 20,
    alignItems: 'center',
    backgroundColor: '#1a5276',
    marginBottom: 8,
  },
  avatar: {
    width: 72,
    height: 72,
    borderRadius: 36,
    marginBottom: 10,
  },
  name: {
    color: '#fff',
    fontSize: 18,
    fontWeight: '600',
  },
});

export default CustomDrawerContent;

Hasła z dokumentacji w tej lekcji

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Które biblioteki są wymagane dla Drawer Navigator?

  2. 2. Jak ustawić Drawer po prawej stronie ekranu?

Zadania praktyczne w grze

  • Klikanie w kolejności

    Kliknij elementy otwierania Drawer programowo:

  • Edytor kodu

    Uzupełnij kod CustomDrawerContent.

Przydatne artykuły