Создание кастомной кнопки для Tab Navigation
По умолчанию React Navigation предоставляет базовый внешний вид вкладок (табов). Но давайте будем честными: они не всегда отражают стиль приложения, над которым мы работаем. В реальных проектах нужно добавить иконки, настроить цвета или даже заменить стандартные вкладки на уникальные компоненты. Это и будет нашей задачей.
Шаг 1: базовая настройка
Сначала создадим новый файл CustomTabBarButton.tsx, где мы будем хранить наш кастомный компонент.
// components/CustomTabBarButton.tsx
import React from 'react';
import { TouchableOpacity, Text, StyleSheet } from 'react-native';
interface CustomTabBarButtonProps {
label: string; // Текст вкладки
onPress: () => void; // Функция, которая срабатывает при нажатии
isFocused: boolean; // Активна ли данная вкладка
}
const CustomTabBarButton: React.FC<CustomTabBarButtonProps> = ({ label, onPress, isFocused }) => {
return (
<TouchableOpacity
style={[styles.container, isFocused && styles.focused]}
onPress={onPress}
>
<Text style={[styles.label, isFocused && styles.labelFocused]}>
{label}
</Text>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingVertical: 10,
backgroundColor: '#fff', // Базовый цвет вкладки
},
focused: {
backgroundColor: '#4CAF50', // Цвет, когда вкладка активна
},
label: {
fontSize: 14,
color: '#999', // Цвет текста по умолчанию
},
labelFocused: {
color: '#fff', // Цвет текста, когда вкладка активна
},
});
export default CustomTabBarButton;
Здесь мы используем TouchableOpacity для создания кнопки и добавляем стили для активного состояния вкладки с помощью пропса isFocused.
Шаг 2: подключение к Bottom Tab Navigation
Теперь подключим наш компонент CustomTabBarButton к Bottom Tab Navigation в App.tsx (или любом другом файле, где вы описали createBottomTabNavigator).
import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import ScreenA from './screens/ScreenA';
import ScreenB from './screens/ScreenB';
import CustomTabBarButton from './components/CustomTabBarButton';
const Tab = createBottomTabNavigator();
const App: React.FC = () => {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarButton: (props) => (
<CustomTabBarButton
{...props}
label={route.name}
isFocused={props.accessibilityState?.selected || false}
/>
),
})}
>
<Tab.Screen name="Home" component={ScreenA} />
<Tab.Screen name="Settings" component={ScreenB} />
</Tab.Navigator>
);
};
export default App;
Разбор кода:
- Мы передаём
tabBarButtonвscreenOptions, чтобы заменить стандартную кнопку вкладки на наш кастомный компонент. - Передаём значение
selectedизprops.accessibilityStateдля определения активного состояния вкладки. - Используем имя экрана
route.nameв качестве текста кнопки.
Шаг 3: добавление иконок в кнопки
Пустые кнопки — это скучно, согласны? Давайте добавим иконки. Для этого установим популярную библиотеку react-native-vector-icons.
npm install react-native-vector-icons
Теперь добавим иконки в кастомную кнопку:
// components/CustomTabBarButton.tsx
import React from 'react';
import { TouchableOpacity, Text, StyleSheet } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome'; // Подключаем библиотеку иконок
interface CustomTabBarButtonProps {
label: string;
onPress: () => void;
isFocused: boolean;
iconName: string; // Новый пропс для имени иконки
}
const CustomTabBarButton: React.FC<CustomTabBarButtonProps> = ({ label, onPress, isFocused, iconName }) => {
return (
<TouchableOpacity
style={[styles.container, isFocused && styles.focused]}
onPress={onPress}
>
<Icon name={iconName} size={20} color={isFocused ? '#fff' : '#999'} />
<Text style={[styles.label, isFocused && styles.labelFocused]}>
{label}
</Text>
</TouchableOpacity>
);
};
export default CustomTabBarButton;
Обновляем App.tsx:
Теперь передадим имя иконки для каждой вкладки:
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarButton: (props) => (
<CustomTabBarButton
{...props}
label={route.name}
isFocused={props.accessibilityState?.selected || false}
iconName={route.name === 'Home' ? 'home' : 'cog'} // Иконки для экранов
/>
),
})}
>
<Tab.Screen name="Home" component={ScreenA} />
<Tab.Screen name="Settings" component={ScreenB} />
</Tab.Navigator>
Теперь вместо скучных пустых кнопок у нас есть иконки, которые динамически меняются в зависимости от текущего экрана.
Создание кастомной кнопки для Drawer Navigation
Drawer Navigation часто используется для "скрытых" разделов, таких как настройки или информация о приложении. Мы создадим стилизованную кнопку для боковой панели.
Шаг 1: настройка кастомного контента для Drawer
Drawer Navigation поддерживает кастомизацию меню с помощью компонента drawerContent.
// App.tsx
import React from 'react';
import { createDrawerNavigator, DrawerContentScrollView, DrawerItem } from '@react-navigation/drawer';
import ScreenA from './screens/ScreenA';
import ScreenB from './screens/ScreenB';
const Drawer = createDrawerNavigator();
const CustomDrawerContent = (props) => {
return (
<DrawerContentScrollView {...props}>
<DrawerItem
label="Home"
onPress={() => props.navigation.navigate('Home')}
style={{ backgroundColor: '#4CAF50', borderRadius: 5 }}
labelStyle={{ color: '#fff', fontWeight: 'bold' }}
/>
<DrawerItem
label="Settings"
onPress={() => props.navigation.navigate('Settings')}
style={{ backgroundColor: '#4CAF50', borderRadius: 5, marginTop: 10 }}
labelStyle={{ color: '#fff', fontWeight: 'bold' }}
/>
</DrawerContentScrollView>
);
};
const App: React.FC = () => {
return (
<Drawer.Navigator drawerContent={(props) => <CustomDrawerContent {...props} />}>
<Drawer.Screen name="Home" component={ScreenA} />
<Drawer.Screen name="Settings" component={ScreenB} />
</Drawer.Navigator>
);
};
export default App;
Здесь мы заменяем стандартный контент боковой панели на кастомные элементы с помощью DrawerContentScrollView и DrawerItem. Это позволяет настроить внешний вид кнопок.
Обсуждение типичных ошибок
- Проблемы с библиотекой иконок. Если иконки не отображаются, убедитесь, что вы правильно установили
react-native-vector-icons, а также проверили его интеграцию с проектом (особенно на Android). - Передача параметров в кастомные кнопки. Всегда проверяйте типизацию, чтобы избежать ошибок при использовании пропсов.
- Неправильная стилизация. Если стили не применяются, убедитесь, что ваши кастомные кнопки наследуют правильные базовые стили от
TouchableOpacity.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ