Безопасная зона экрана
У современных телефонов экран занимает всю переднюю панель: сверху вырез камеры и строка состояния с часами, снизу полоска жестов. Безопасная зона (safe area) — часть экрана, которую ничто не закрывает. Содержимое, особенно текст и кнопки, должно находиться в ней.
Когда это нужно
Шапка стека и панель вкладок Expo Router сами учитывают безопасную зону. Проблема появляется на экранах без шапки. Скройте шапку в списке задач:
// app/_layout.tsx
import { Stack } from 'expo-router';
export default function RootLayout() {
return <Stack screenOptions={{ headerShown: false }} />;
}Теперь заголовок «Мои задачи» на iPhone окажется под часами и вырезом камеры, а на Android — под строкой состояния.
SafeAreaView
Компонент SafeAreaView из пакета react-native-safe-area-context добавляет отступы ровно по размеру системных элементов. Пакет уже установлен в шаблоне Expo.
// app/index.tsx
import { Text } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
export default function Index() {
return (
<SafeAreaView style={{ flex: 1, backgroundColor: '#fff' }}>
<Text style={{ fontSize: 24, padding: 16 }}>Мои задачи</Text>
</SafeAreaView>
);
}Заголовок опустится ниже часов и выреза. Белый фон при этом заполнит экран целиком, включая область под строкой состояния, — отступ добавляется внутрь.
Проп edges выбирает стороны: edges={['top']} добавит отступ только сверху. Это нужно, если снизу экрана находится панель вкладок, которая уже учитывает нижнюю зону.
useSafeAreaInsets
Хук возвращает размеры отступов числами — их можно использовать в любом стиле. Например, прижать кнопку «Добавить» к низу экрана над полоской жестов:
// app/index.tsx
import { View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import AppButton from '@/components/AppButton';
export default function Index() {
const insets = useSafeAreaInsets();
return (
<View style={{ flex: 1, paddingTop: insets.top, paddingBottom: insets.bottom + 8 }}>
<View style={{ flex: 1 }} />
<AppButton title="Добавить задачу" onPress={() => {}} />
</View>
);
}insets содержит четыре числа: top, bottom, left, right. На iPhone с вырезом top около 50–60, на старых телефонах с кнопкой «Домой» — около 20.
Провайдер
Компоненты безопасной зоны работают внутри SafeAreaProvider. Expo Router добавляет его сам, поэтому в проектах с Expo Router оборачивать приложение вручную не нужно.
Частая ошибка
Импортировать SafeAreaView из react-native. Этот старый компонент работает только на iOS, на Android ничего не делает и в React Native 0.81 объявлен устаревшим. Импортируйте SafeAreaView из react-native-safe-area-context.