💻
React Native
  • 👨‍💻Full-Stack Web Developer
  • 📚Теорія
    • 1️⃣Налаштування робочого середовища
      • Вступ
      • Налаштування середовища розробки
      • Перший проект
      • Налаштування емуляції Android (Android Studio + JDK)
      • Налаштування емуляції Iphone (Xcode)
      • Запуск проекту на віртуальних пристроях
      • Expo Snack
    • 2️⃣Верстка і стилізація
      • Функціональні та класові компоненти
      • Базові компоненти
      • Фундаментальні концепції React в React Native
      • Стилізація компонентів
      • Стилізація залежно від платформи
      • Кольори
      • Зображення
      • Векторна графіка
      • Розташування компонентів
      • Робота зі шрифтами
      • Колекції даних
      • Дебаг застосунку
    • 3️⃣Обробка подій
      • Обробка подій
      • Обробка текстових інпутів
      • Інпути в фокусі
      • Форма для збору даних
      • Робота з клавіатурою
      • Перехоплення подій
    • 4️⃣Навігація
      • Підключення навігації
      • Перемикання екранів
      • Передача параметрів між екранами
      • Хедер екрану
      • Вкладена навігація
      • Нижня навігація
    • 5️⃣Нативні компоненти
      • Камера
      • Мапи
      • Геолокація
    • 👷Практика
      • 1️⃣Завдання 1
      • 2️⃣Завдання 2
      • 3️⃣Завдання 3
      • 4️⃣Завдання 4
      • 5️⃣Завдання 5
      • 6️⃣Завдання 6
      • 7️⃣Завдання 7
    • Додаткові покликання
  • Про мене
    • Про мене
Powered by GitBook
On this page
  • Пропси (для компонентів Tab.Navigator та Tab.Screen)
  • Опції (параметри для пропсів screenOptions та options)
  • Хедер і повʼязані опції
  • Події (Events)
  • Хелпери
  • ПРАКТИЧНІ ПРИКЛАДИ НИЖНЬОГО МЕНЮ
  • Приклад нижнього меню зі стилізацією кожного окремого табу навігації (в Tab.Screen)
  • Приклад нижнього меню зі стилізацією табів навігації (в Tab.Navigator)
  1. Теорія
  2. Навігація

Нижня навігація

Навігацію в застосунку можна виконати використовуючи верхні чи нижні таби. Розглянемо на прикладі нижньої навігації.

На додачу до раніше встановлених бібліотек маршрутизації потрібно встановити ще цей пакет.

terminal
npm install @react-navigation/bottom-tabs

Припустимо, що ми створили з нуля новий додаток і налаштували в ньому перемикання між трьома скрінами, які поки реалізуємо, як функціональні компоненти всередині нашого ж головного компонента MyTabs.js. В App.js також потрібно налаштувати маршрутизацію. На цьому етапі на базовому рівні перемикання екранів уже працює.

App.js
import { NavigationContainer } from "@react-navigation/native";
import { MyTabs } from "./MyTabs";

export default function App() {
  return (
    <NavigationContainer>
      <MyTabs />
    </NavigationContainer>
  );
}
MyTabs.js
import { View, Text, StyleSheet } from "react-native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";

const Tab = createBottomTabNavigator();

const Home = () => {
  return (
    <View style={styles.container}>
      <Text>HomeScreen</Text>
    </View>
  );
};

const Settings = () => {
  return (
    <View style={styles.container}>
      <Text>SettingsScreen</Text>
    </View>
  );
};

const Info = () => {
  return (
    <View style={styles.container}>
      <Text>InfoScreen</Text>
    </View>
  );
};

export const MyTabs = () => {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={Home} />
      <Tab.Screen name="Settings" component={Settings} />
      <Tab.Screen name="Info" component={Info} />
    </Tab.Navigator>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});

Розберемо компонент MyTabs.js.

  1. Підключаємо createBottomTabNavigator.

  2. Створюємо Tab.

  3. Home, Settings і Info це просто компоненти, які відображатимуться на екрані при натисканні тієї чи іншої кнопки на нижньому меню. Можна реалізувати. компонентами в окремих файлах і просто заімпортувати згори.

  4. Компонент MyTabs. У ньому реалізуємо нашу навігацію. Він експортується і підключається в App.js

  5. В компонент Tab.Navigator огортаємо наші кнопки нижнього меню.

  6. Компонент Tab.Screen описує послідовно кнопки нашого нижнього меню. Він як мінімум приймає два пропси. name - назва кнопки. При цьому ця ж назва буде відображатися в хедері. component - компонент, який буде відображатися при його натисканні.

Пропси (для компонентів Tab.Navigator та Tab.Screen)

Детальний опис пропсів наведено в офіційній документації.

id - опціональний проп для роботи з навігацією.

initialRouteName - імʼя роута, який буде завантажуватись першим(за замовчанням першим завантажиться той, який в порядку перший). Припустимо, першим хочемо завантажити роут Settings, тоді код буде таким.

<Tab.Navigator initialRouteName="Settings"></Tab.Navigator>

screenOptions - налаштування вигляду нижнього меню. Докладніше розглянуто нижче.

backBehavior - працює з кнопкою назад або жестом назад.

detachInactiveScreens - використовується для позначення неактивних екранів. За замовчанням true.

sceneContainerStyle - Об’єкт стилю для компонента, що обгортає вміст екрана.

!!!! Поки розбираюся, як воно працює, тому цей шматок можливо доповниться

Опції (параметри для пропсів screenOptions та options)

// Заголовок не буде показуватись для всіх Tab.Screen
<Tab.Navigator screenOptions={{ headerShown: false }}></Tab.Navigator>
// Заголовок не буде показуватись тільки для Tab.Screen компонента Settings 
<Tab.Screen name="Settings" component={Settings} options={{ headerShown: false }}/> 

title - варіант присвоєння тексту заголовку (і відповідно назви кнопки)

<Tab.Navigator screenOptions={{ title: "Header" }}></Tab.Navigator>
<Tab.Screen
        name="Settings"
        component={Settings}
        options={{ title: "Settings Header" }}
      />

tabBarLabel - Назва лейбла закладки на нижній навігації. Але не змінює напису Хедера.

<Tab.Screen
        name="Home"
        component={Home}
        options={{ tabBarLabel: "To Home" }}
      />

tabBarShowLabel - чи показувати підписи закладинок.

<Tab.Navigator screenOptions={{ tabBarShowLabel: false }}></Tab.Navigator>

tabBarLabelPosition - розміщення підпису (лейбла) іконки закладинки. За замовчанням визначається автоматично в залежності від розмірів екрана пристрою. Може бути below-icon (знизу іконки), beside-icon (збоку від іконки).

<Tab.Navigator screenOptions={{ tabBarLabelPosition: "beside-icon" }}></Tab.Navigator>

tabBarLabelStyle - стиль підпису іконки (обʼєкт стилів)

<Tab.Navigator screenOptions={{ tabBarLabelStyle: { color: "red" } }}></Tab.Navigator>

tabBarIcon - функція, якій передають { focused: boolean, color: string, size: number } і яка повертає React.Node для показу в нижньому меню. Наприклад, ми хочемо міняти іконку в залежності у фокусі закладника чи ні.

import { Ionicons } from "@expo/vector-icons";
// код
<Tab.Screen
  name="Info"
  component={Info}
  options={{
    tabBarIcon: ({ focused, color, size }) => {
      let iconName = focused
        ? "ios-information-circle"
        : "ios-information-circle-outline";
      return <Ionicons name={iconName} size={size} color={color} />;
     },
  }}
/>

А якщо, наприклад прописати такі налаштування, то при фокусі буде мінятися іконка, збільшуватися в розмірі та міняти колір із зеленого на червоний.

<Tab.Screen
  name="Info"
  component={Info}
  options={{
    tabBarIcon: ({ focused, color, size }) => {
      let iconName = focused
        ? "ios-information-circle"
        : "ios-information-circle-outline";
      let newColor = focused ? "red" : "green";
      let newSize = focused ? 37 : 27;
      return <Ionicons name={iconName} size={newSize} color={newColor} />;
    },
  }}
/>

tabBarIconStyle - стиль блоку іконки (обʼєкт стилів)

tabBarBadge - бейджик для кнопки. Кружечок чи овал у верхньому правому куті іконки. Приймає значення число чи рядок.

<Tab.Screen
  name="Home"
  component={Home}
  options={{ tabBarBadge: "Yes" }}
/>

tabBarBadgeStyle - стиль бейджика (обʼєкт стилів)

<Tab.Screen
  name="Home"
  component={Home}
  options={{
  tabBarBadge: "Yes",
  tabBarBadgeStyle: { backgroundColor: "blue" },
  }}
/>

tabBarAccessibilityLabel - мітка доступності, яка читається скрінрідерами.

<Tab.Screen
   name="Home"
   component={Home}
   options={{
   tabBarAccessibilityLabel: "Home",
   }}
/>

tabBarTestID - Ідентифікатор для пошуку цієї кнопки вкладки в тестах.

tabBarButton - Функція, яка повертає React-елемент для відтворення як кнопки панелі вкладок. Він огортає піктограму та мітку. За замовчуванням рендериться як Pressable. Ви можете вказати спеціальну реалізацію тут:

!!!! Поки розбираюся, як воно працює, тому цей шматок доповниться

tabBarActiveTintColor - встановлює колір іконки і тексту активної вкладинки.

<Tab.Navigator screenOptions={{ tabBarActiveTintColor: "orange" }}></Tab.Navigator>

tabBarInactiveTintColor - встановлює колір іконки і тексту неактивної вкладинки.

<Tab.Navigator screenOptions={{ tabBarInactiveTintColor: "purple" }}></Tab.Navigator>

tabBarActiveBackgroundColor - встановлює колір фону активної вкладинки.

<Tab.Navigator screenOptions={{ tabBarActiveBackgroundColor: "yellow" }}></Tab.Navigator>

tabBarInactiveBackgroundColor - встановлює колір фону активної вкладинки.

<Tab.Navigator screenOptions={{ tabBarInactiveBackgroundColor: "grey" }}></Tab.Navigator>

tabBarHideOnKeyboard - приховування панелі вкладок, коли відкривається клавіатура. За замовчуванням значення false.

<Tab.Navigator screenOptions={{ tabBarHideOnKeyboard: true }}></Tab.Navigator>

tabBarItemStyle - стиль обʼєкта однієї закладинки.

<Tab.Screen
  name="Home"
  component={Home}
  options={{ tabBarItemStyle: { backgroundColor: "red" } }}
/>
<Tab.Navigator
  screenOptions={{
    tabBarStyle: {
      position: "absolute",
      bottom: 50,
      backgroundColor: "#44FFFF",
      borderRadius: 30,
       height: 50,
      paddingBottom: 0,
    },
  }}
>

tabBarBackground - Функція повертає Reit-елемент щоб використовувати як бекграунд для всієї панелі меню. Можна зарендерити картинку, градієнт і розмиття.

import { BlurView } from 'expo-blur';

// ...

<Tab.Navigator
  screenOptions={{
    tabBarStyle: { position: 'absolute' },
    tabBarBackground: () => (
      <BlurView tint="light" intensity={100} style={StyleSheet.absoluteFill} />
    ),
  }}
>

lazy - Чи має цей екран відображатися під час першого доступу. За замовчуванням значення true. Встановіть значення false, якщо ви хочете відобразити екран початкового рендерингу.

unmountOnBlur - Чи слід відключати цей екран під час переходу з нього. Демонтування екрана скидає будь-який локальний стан на екрані, а також стан вкладених навігаторів на екрані. За замовчуванням значення false.

Не рекомендовано вмикати цей параметр, оскільки користувачі не очікують, що їх історія навігації буде втрачена під час перемикання вкладок. Якщо таки вирішите ввімкнути цю опцію, подумайте, чи справді це забезпечить кращий досвід для користувача.

freezeOnBlur - Набуває булеве значення. Вказує чи потрібно запобігати повторному рендерингу неактивних екранів. За замовчуванням значення false. За замовчуванням значення true, коли enableFreeze() із пакета react-native-screens імпортовано у верхній частині програми.

Потрібна версія react-native-screens >=3.16.0.

Підтримується лише на iOS і Android.

Хедер і повʼязані опції

header - Спеціальний заголовок для використання замість заголовка за умовчанням.

Приймає функцію, яка повертає React-елемент для відображення як заголовок. Функція отримує в якості аргументу об’єкт, що містить такі властивості:

navigation - об'єкт навігації для поточного екрана.

route - об'єкт маршруту для поточного екрана.

options - параметри для поточного екрана

layout - Розміри екрана, містить властивості висоти (height) та ширини (width).

Далі приклад із офіційної документації (не перевіряв, мабуть легше стандартний хедер сховати і власний хедер прописати)

import { getHeaderTitle } from '@react-navigation/elements';

// ..

header: ({ navigation, route, options }) => {
  const title = getHeaderTitle(options, route.name);

  return <MyHeader title={title} style={options.headerStyle} />;
};

headerShown - використовуємо для показу чи приховування хедера.

<Tab.Screen
  name="Settings"
  component={Settings}
  options={{
    headerShown: false,
  }}
/>
<Tab.Navigator
  screenOptions={{
    headerShown: false, 
  }}
 >

Події (Events)

tabPress - обробляє натиск на кнопку.

tabLongPress - обробляє довготривалий натиск на кнопку.

Хелпери

Навігатор вкладок додає наступний методи до проп навігації.

ПРАКТИЧНІ ПРИКЛАДИ НИЖНЬОГО МЕНЮ

На наступних прикладах розберемо деякі вищезгадані налаштування і подивимося кастомізовані нижні меню. Це важливо, бо в офіційній документації вкрай мало прикладів і пояснень кастомізації.

Приклад нижнього меню зі стилізацією кожного окремого табу навігації (в Tab.Screen)

Розберемо цей приклад покроково.

Загальні налаштування для всіх табів Tab.Navigator:

<Tab.Navigator
  initialRouteName="Feed"
  screenOptions={{
    tabBarShowLabel: false,
    // headerShown: false,
    tabBarStyle: {
      paddingBottom: 20,
     height: 83,
    }
  }}
>

Тут для всіх табів вимикаємо показ підписів під іконками. Закоменчене налаштування показу хедера. Якщо хочемо його приховати для всіх скрінів, то треба його розкоментувати. У налаштуванні tabBarStyle задані загальний стиль для нижнього меню табів.

Налаштування зовнішнього вигляду і поведінки табу для першого скріна:

<Tab.Screen
  name="Feed"
  component={Feed}  
  options={{
  tabBarActiveTintColor: "#FF6C00",
  tabBarInactiveTintColor: "#212121",
  tabBarIcon: ({ color, size }) => (
    <AntDesign name="appstore-o" color={color} size={size} />
     ),
  }}
/>

Тут задаємо колір активної і неактивної іконки. Найбільше цікавить синтаксис tabBarIcon. Як було сказано раніше це функція, яка приймає пропси focused, color і size, і може формувати в зележності від цих даних зовнішній вигляд наших іконок. У прикладі неявне повернення. Давайте трохи (просто для наочності) підправимо наш код, щоб переконатися, що приходить в пропсах.

<Tabs.Screen
  name="Feed"
  component={Feed}
  options={{
    tabBarActiveTintColor: "#FF6C00",
    tabBarInactiveTintColor: "#212121",
    tabBarIcon: (props) => {
      console.log("props", props);
      return (
        <AntDesign
          name="appstore-o"
          color={props.color}
          size={props.size}
        />
      );
    },
  }}
/>

Налаштування зовнішнього вигляду і поведінки табу для третього скріна:

Далі логічніше передивитися налаштування табу третього скріна. Як видно в попередньому прикладі ми ніяк не обробляли проп фокусу. Тож тут ми будемо міняти в залежності від фокусу скріна нашу іконку (обведенну на залиту). А також можна міняти і розмір самої іконки (давайте із 25 до 35 пікселів).

<Tab.Screen
  name="Profile"
  component={Profile}
  options={{
    tabBarLabel: 'Profile',
    tabBarActiveTintColor: "#FF6C00",
    tabBarInactiveTintColor: "#212121",
    tabBarIcon: ({ focused, color, size }) => {
      let iconName = focused ? "person" : "person-outline";
      let iconSize = focused ? 35 : 25;
      return <Ionicons name={iconName} color={color} size={iconSize} />;
    },
   }}
/>

Налаштування зовнішнього вигляду і поведінки табу для другого скріна:

у цьому прикладі ускладнимо кнопку. Окрім зміни кольору і іконки при її фокусі додамо фоновий овал, який теж буде змінювати колір при фокусі. Тут задамо і колір неактивних іконок для інших табів. В налаштуваннях tabBarIcon описуємо в перемінних колір іконки і колір бекграуну. Назву іконки не визначаємо в перемінну, бо іконки з різних бібліотек, тому ми будемо формувати повністю весь компонент іконки в залежності від фокусу. Рендериться по суті стилізований View із тернарним вибором іконки в залежності від фокусу.

<Tab.Screen
   name="Notifications"
  component={Notifications}
  options={{
    tabBarInactiveTintColor: "#212121",
    tabBarIcon: ({ focused, color, size }) => {
      let icoColor = focused ? "#BDBDBD" : "#ffffff";
      let bgColor = focused ? "#F6F6F6" : "#FF6C00";
      return (
        <View
          style={{
            backgroundColor: bgColor,
            borderRadius: 20,
            height: 40,
            width: 70,
            alignItems: "center",
            justifyContent: "center",
          }}
         >
          {focused ? (
            <Feather name="trash-2" color={icoColor} size={size} />
          ) : (
            <Octicons name="plus" color={icoColor} size={size} />
           )}
        </View>
      );
    },
  }}
/>

Приклад нижнього меню зі стилізацією табів навігації (в Tab.Navigator)

В даному прикладі у Tab.Screen ми лишаємо лише пропи name i component, які відповідно містять назву скріна і компонент, який завантажиться. Всі інші налаштування робимо в Tab.Navigator. Ось шаблон на який нарощуватимемо налаштування.

<Tab.Navigator initialRouteName="Feed" >
  <Tab.Screen name="Feed" component={Feed} />
  <Tab.Screen name="Notifications" component={Notifications} />
  <Tab.Screen name="Profile" component={Profile} />
</Tab.Navigator>

В проп screenOptions можна вписати анонімну функцію, яка повертатиме обʼєкт налаштувань.

<Tab.Navigator initialRouteName="Feed" screenOptions={()=>{}} >

Давайте дізнаємося, які параметри вона має.

<Tabs.Navigator
  screenOptions={(props) => {
    console.log("props", props);
  }}
>

Для кожного Tab.Screen cформуєтсья такий обʼєкт пропсів (в даному прикладі три штуки для Feed, Notifications і Profile:

Тут нас цікавить проп route (і відповідно його параметр name). І ми можемо по цьому імені сформувати кожну кнопку табу. Просто буде перевірятися збіг імені. А застилізуємо по прикладу як це було вище використавуючи tabBarIcon (яка також є колбек функцією - дивись приклад раніше ). І отримаємо такий код:

<Tab.Navigator
  screenOptions={({ route }) => {
    return {
      tabBarActiveTintColor: "#FF6C00",
      tabBarInactiveTintColor: "#212121",
      tabBarIcon: ({ focused, color, size }) => {
        if (route.name === "Feed") {
          return <AntDesign name="appstore-o" color={color} size={size} />;
        } else if (route.name === "Notifications") {
          let icoColor = focused ? "#BDBDBD" : "#ffffff";
          let bgColor = focused ? "#F6F6F6" : "#FF6C00";
          return (
            <View
              style={{
                backgroundColor: bgColor,
                borderRadius: 20,
                height: 40,
                width: 70,
                alignItems: "center",
                justifyContent: "center",
              }}
            >
              {focused ? (
                <Feather name="trash-2" color={icoColor} size={size} />
              ) : (
                <Octicons name="plus" color={icoColor} size={size} />
              )}
            </View>
          );
        } else if (route.name === "Profile") {
          let iconName = focused ? "person" : "person-outline";
          let iconSize = focused ? 35 : 25;
          return <Ionicons name={iconName} color={color} size={iconSize} />;
        }
     },
    };
   }}
>

Тепер приберемо підписи табів, а також хедер і застилізуємо відступи табів. Тобто запишемо в обʼєкт screenOptions, який повертається такий код:

tabBarShowLabel: false,
headerShown: false,
tabBarStyle: {
paddingBottom: 20,
height: 83,
},
Код
    <Tab.Navigator
      screenOptions={({ route }) => {
        return {
          tabBarShowLabel: false,
          headerShown: false,
          tabBarStyle: {
          paddingBottom: 20,
          height: 83,
          },
          tabBarActiveTintColor: "#FF6C00",
          tabBarInactiveTintColor: "#212121",
          tabBarIcon: ({ focused, color, size }) => {
            if (route.name === "Feed") {
              return <AntDesign name="appstore-o" color={color} size={size} />;
            } else if (route.name === "Notifications") {
              let icoColor = focused ? "#BDBDBD" : "#ffffff";
              let bgColor = focused ? "#F6F6F6" : "#FF6C00";
              return (
                <View
                  style={{
                    backgroundColor: bgColor,
                    borderRadius: 20,
                    height: 40,
                    width: 70,
                    alignItems: "center",
                    justifyContent: "center",
                  }}
                >
                  {focused ? (
                    <Feather name="trash-2" color={icoColor} size={size} />
                  ) : (
                    <Octicons name="plus" color={icoColor} size={size} />
                  )}
                </View>
              );
            } else if (route.name === "Profile") {
              let iconName = focused ? "person" : "person-outline";
              let iconSize = focused ? 35 : 25;
              return <Ionicons name={iconName} color={color} size={iconSize} />;
            }
          },
        };
      }}
     >

Ну і насамкінець давайте зробимо так, щоб, дві бокові кнопки не версталися, якшо ми вибираємо скрін центральної кнопки.

КАСТОМНІ ХЕДЕРИ

Посилання на офіційну документацію:

PreviousВкладена навігаціяNextНативні компоненти

Last updated 1 year ago

Всі нижченаведені налаштування можна протестувати онлайн у вкладці браузера у .

tabBar - функція, яка повертає React-елемент для відображення як панелі вкладок. Якщо потрібно кастомно стилізувати меню навігації. Код громіздкий і краще дивитися в .

Наступні можна використовувати для налаштування екранів у навігаторі. Їх можна вказати в пропі screenOptions для Tab.Navigator або в пропі options у Tab.Screen. По суті можемо вказати опції для кожної окремої кнопки в Tab.Screen і загальне правило для всіх кнопок в Tab.Navigator.

tabBarStyle - стиль об'єкта навігації. Наприклад, можна встановити колір фону. А щоб показати скрін під меню навігації можна встановити position в absolute і рухати меню (top, bottom). Можна скинути паддінг (з 30 до 10, наприклад) якщо він здається великим. Задати кастомну висоту блоку навігації, або скруглити кути. Додаткові налаштування в офіційній .

Використовуючи , переконайтеся, що також встановлено position: 'absolute' у tabBarStyle. Вам також знадобиться використати useBottomTabBarHeight(), щоб додати нижній відступ до вашого вмісту.

Повний перелік налаштувань хедера можна знайти в . Тут наведемо необхідний мінімум. хедера виконують в пропсах screenOptions для Tab.Navigator і options для Tab.Screen. Не обов’язково безпосередньо використовувати @react-navigation/elements, щоб використовувати ці параметри.

Навігатор може на певні дії. Підтримувані події:

Повний розбір цього функціоналу в .

jumpTo - Перехід до наявного екрана в навігаторі вкладок. Докладніше в .

📚
4️⃣
цьому шаблоні проекту на Snack
офіційній документації
опції
документації
BlurView
документації
Налаштування
обробляти івенти
офіційній документації
документації
Спробувати цей приклад на Snack
Нижня навігація
Options for screen
Material Tab Bottom Navigation