Safe area — notch, status bar, pastki panel

~10 daq · React Native · Stil va layout

Muammodan boshlaylik

Ekran tepasiga sarlavha qo'ydingiz. Zamonaviy iPhone da sarlavha "notch" (kamera kesimi) yoki "Dynamic Island" ostida qolib ketdi — matnning yarmi ko'rinmaydi. Pastdagi tugma esa uy indikatori (pastki chiziq) bilan ustma-ust tushdi va bosish qiyin. Android da status bar matnni yopib qo'ydi.

Zamonaviy telefonlarning ekrani to'rtburchak emas: yumaloq burchaklar, kamera kesimlari, tizim panellari. Safe area — ekranning kontent uchun xavfsiz qismi.


react-native-safe-area-context

Expo shablonida allaqachon o'rnatilgan. Agar yo'q bo'lsa:

npx expo install react-native-safe-area-context

Expo Router uni avtomatik ildizga ulaydi (SafeAreaProvider).


SafeAreaView

import { SafeAreaView } from 'react-native-safe-area-context';

export default function Ekran() {
  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: 'white' }}>
      <Text style={{ fontSize: 24, fontWeight: '700', padding: 16 }}>Bosh sahifa</Text>
      {/* ... */}
    </SafeAreaView>
  );
}

SafeAreaView — notch, status bar va pastki indikator o'lchamiga teng padding ni avtomatik qo'shadi.

[!WARNING] react-native dagi SafeAreaView emas, react-native-safe-area-context dagisini import qiling. O'rnatilgan variant faqat iOS da ishlaydi va eskirgan.

Faqat ba'zi tomonlar

<SafeAreaView edges={['top']} style={{ flex: 1 }}>

edges: 'top', 'bottom', 'left', 'right'. Masalan, pastda tab panel bor bo'lsa (u o'zi pastki safe area ni hisobga oladi) — faqat top.


useSafeAreaInsets — aniq o'lchamlar

Ko'pincha padding ni o'zingiz boshqarish qulayroq:

import { useSafeAreaInsets } from 'react-native-safe-area-context';

export default function Ekran() {
  const insets = useSafeAreaInsets();
  // { top: 59, bottom: 34, left: 0, right: 0 } — iPhone 15 da

  return (
    <View style={{ flex: 1 }}>
      <View style={{ paddingTop: insets.top + 8, paddingHorizontal: 16, backgroundColor: '#0284c7' }}>
        <Text style={{ color: 'white', fontSize: 20, fontWeight: '700', paddingBottom: 12 }}>Do'kon</Text>
      </View>

      <ScrollView style={{ flex: 1 }}>{/* ... */}</ScrollView>

      <View style={{ paddingBottom: Math.max(insets.bottom, 12), paddingTop: 12, paddingHorizontal: 16, borderTopWidth: 1, borderColor: '#e2e8f0' }}>
        <Tugma matn="Savatga qo'shish" />
      </View>
    </View>
  );
}
  • Sarlavha foni (ko'k) notch ostigacha cho'ziladi — chiroyli, lekin matn xavfsiz joyda
  • Math.max(insets.bottom, 12) — pastki indikatorli telefonda 34, tugmali eski telefonda kamida 12

Bu — "edge-to-edge" dizayn: fon ekranning chetigacha, kontent — safe area ichida.


Navigatsiya bilan

Expo Router da Stack sarlavhasi (headerShown: true) va Tabs paneli safe area ni o'zi hisobga oladi. Shuning uchun:

Ekran Nima kerak
Stack sarlavhasi bor Tepaga hech narsa kerak emas
Sarlavhasiz (headerShown: false) SafeAreaView edges={['top']} yoki insets.top
Tablar ichida Pastga hech narsa kerak emas
Pastda o'z tugmangiz, tablar yo'q insets.bottom

Ikki marta qo'shish — keraksiz katta bo'shliq. Har bir ekranda kim safe area ni boshqarayotganini biling.


Android: edge-to-edge

Yangi Android versiyalari (15+) ilovalarni edge-to-edge rejimga o'tkazadi: kontent status bar va navigatsiya paneli ostiga ham chiziladi. Expo ning yangi SDK lari buni standart qiladi. Natija — Android da ham iOS dagi kabi insets ni hisobga olish majburiy. Eski "Android da status bar o'zi joy egallaydi" degan taxminlar endi ishlamaydi.


Sinash

  • iPhone simulator — notch li va Dynamic Island li modellar (iPhone 15, 15 Pro)
  • Android emulyator — imo-ishorali navigatsiya va 3 tugmali navigatsiya
  • Yotiq holat — safe area chap va o'ngda paydo bo'ladi (notch yon tomonda)

Nima uchun shunday?

Nima uchun tizim safe area ni avtomatik qo'llamaydi — kontentni xavfsiz joyga o'zi joylashtirsa bo'lmaydimi?

Chunki ko'pincha fon chetigacha bo'lishi kerak, kontent esa yo'q. Ko'k sarlavha foni notch ostida ham ko'k bo'lishi chiroyli; rasm galereyasi butun ekranni egallashi kerak; xarita esa chetma-chet. Tizim qaysi element "fon" va qaysi biri "kontent" ekanini bilmaydi. Shuning uchun u faqat o'lchamlarni beradi (insets), qaror esa sizda — har bir ekran o'zi hal qiladi.


Xulosa

Eslab qoling:

  • Safe area — notch, Dynamic Island, status bar va pastki indikatordan holi qism
  • react-native-safe-area-context dan SafeAreaView — react-native dagisi emas
  • edges={['top']} — faqat kerakli tomonlar
  • useSafeAreaInsets() — aniq qiymatlar; fon chetigacha, kontent — ichkarida
  • Math.max(insets.bottom, 12) — eski telefonlarda ham bo'shliq
  • Stack sarlavhasi va Tabs safe area ni o'zi hisobga oladi — ikki marta qo'shmang
  • Yangi Android — edge-to-edge, insets majburiy

Keyingi dars

19-dars: FlatList — katta ro'yxatlar, keyExtractor, pull-to-refresh