Урок 09

Хедеры и опции экранов

Хедер — верхняя панель экрана с заголовком и кнопками. Настраивается через options.

Базовые опции

<Stack.Screen
    name="Details"
    component={DetailsScreen}
    options={{
        title: 'Детали',
        headerShown: true,
        headerBackTitle: 'Назад',
        headerBackVisible: true,
        headerTitleAlign: 'center',  // 'left' | 'center'
    }}
/>

Стили хедера

options={{
    headerStyle: { backgroundColor: '#c1442e' },
    headerTintColor: '#fff',
    headerTitleStyle: { fontWeight: 'bold', fontSize: 18 },
    headerShadowVisible: false,
    headerTransparent: true,
    headerBlurEffect: 'light',  // 'light' | 'dark' | 'extraLight' | 'regular' | 'prominent' | 'systemMaterial'
}}

Кнопки

options={{
    headerLeft: () => (
        <Pressable onPress={() => navigation.goBack()}>
            <Ionicons name="arrow-back" size={24} />
        </Pressable>
    ),
    headerRight: () => (
        <View style={{ flexDirection: 'row', gap: 16 }}>
            <Pressable onPress={onShare}>
                <Ionicons name="share-outline" size={24} />
            </Pressable>
            <Pressable onPress={onMore}>
                <Ionicons name="ellipsis-horizontal" size={24} />
            </Pressable>
        </View>
    ),
}}

Большой заголовок (iOS)

options={{
    headerLargeTitle: true,
    headerLargeTitleStyle: { fontSize: 34, fontWeight: 'bold' },
    headerLargeTitleShadowVisible: false,
}}

Поиск в хедере

options={{
    headerSearchBarOptions: {
        placeholder: 'Поиск',
        onChangeText: (event) => setQuery(event.nativeEvent.text),
        onCancelButtonPress: () => setQuery(''),
        hideWhenScrolling: true,
    },
}}

Анимация появления

options={{
    animation: 'slide_from_right',  // 'default' | 'fade' | 'flip' | 'simple_push' | 'slide_from_bottom' | 'slide_from_right' | 'slide_from_left' | 'none'
    animationDuration: 300,
    presentation: 'card',  // 'card' | 'modal' | 'transparentModal' | 'fullScreenModal' | 'containedModal' | 'containedTransparentModal' | 'formSheet'
}}

Жесты

options={{
    gestureEnabled: true,
    gestureDirection: 'horizontal',  // 'horizontal' | 'vertical'
    fullScreenGestureEnabled: true,
    gestureResponseDistance: 100,
}}

fullScreenGestureEnabled — свайп с любого места экрана.

Статус-бар

options={{
    statusBarStyle: 'auto',  // 'auto' | 'inverted' | 'light' | 'dark'
    statusBarHidden: false,
    statusBarAnimation: 'fade',
}}

Общие опции для всех

<Stack.Navigator
    screenOptions={{
        headerStyle: { backgroundColor: '#fff' },
        headerTintColor: '#000',
        headerTitleAlign: 'center',
        headerShadowVisible: false,
        contentStyle: { backgroundColor: '#fafafa' },
        animation: 'slide_from_right',
    }}
>

Обновление из компонента

function Screen() {
    const navigation = useNavigation();
    const [count, setCount] = useState(0);

    useLayoutEffect(() => {
        navigation.setOptions({
            title: `Счёт: ${count}`,
            headerRight: () => (
                <Pressable onPress={() => setCount((c) => c + 1)}>
                    <Text>+1</Text>
                </Pressable>
            ),
        });
    }, [navigation, count]);

    return <View />;
}

Отключить хедер

options={{ headerShown: false }}

Для экрана без навигации или с кастомным хедером.

Кастомный хедер

options={{ header: (props) => <CustomHeader {...props} /> }}

Итоги

  • options для настройки
  • headerStyle, headerTintColor, headerTitleStyle
  • headerLeft и headerRight для кнопок
  • headerLargeTitle для iOS-стиля
  • headerSearchBarOptions для поиска
  • presentation: 'modal' для модалок