07 β ScrollView, SafeArea va StatusBar¶
β¬ οΈ Oldingi: 06 β Input va tugmalar Β· π Kitob boshi Β· Keyingi: 08 β Ro'yxatlar: FlatList β‘οΈ
Bu bobda: kontent ekranga sig'maganda nima qilamiz?
<ScrollView>bilan sahifani skroll qilinadigan qilamiz. Zamonaviy telefonlardagi notch (kamera o'yig'i) va pastki chiziq kontentni to'sib qo'ymasligi uchunSafeAreaViewni o'rganamiz. Yuqoridagi soat/batareya zonasiniStatusBarbilan boshqaramiz, rasmlarni chuqurroq ko'ramiz va klaviatura inputni to'smasligi uchunKeyboardAvoidingViewdan foydalanamiz.
Muammo: kontent ekranga sig'maydi¶
Oldingi boblarda biz <View> ichida bir nechta element joyladik va ular ekranga chiroyli sig'di. Lekin haqiqiy ilovalarda kontent ko'pincha ekrandan uzunroq bo'ladi: profil sahifasi, sozlamalar ro'yxati, maqola matni, mahsulotlar...
Keling, oddiy bir tajriba qilaylik. Tasavvur qiling, 30 ta qatorni oddiy <View> ichiga joyladingiz:
// app/index.tsx β MUAMMOLI: View skroll qilmaydi!
import { View, Text } from 'react-native';
export default function Index() {
return (
<View style={{ flex: 1, padding: 20 }}>
{Array.from({ length: 30 }).map((_, i) => (
<Text key={i} style={{ fontSize: 18, marginBottom: 16 }}>
Bu {i + 1}-qator matn.
</Text>
))}
</View>
);
}
Telefoningizda buni ochsangiz: dastlabki bir nechta qator ko'rinadi, qolganlari esa ekran tashqarisida qoladi va ularga yetib bo'lmaydi. Barmoq bilan yuqoriga torting β hech narsa bo'lmaydi. <View> qimirlamaydi!
Hayotiy o'xshatish.
<View>β bu deraza. Deraza orqali faqat oldingizdagi narsani ko'rasiz; orqada nima borligini ko'rish uchun derazani siljitolmaysiz.<ScrollView>esa β uzun bir qog'oz varaq o'ralgan rulon. Varaqni qo'lingiz bilan pastga-yuqoriga aylantirib, undagi hamma yozuvni o'qiy olasiz. Mana shu "aylantirish" β skroll.
Ehtiyot bo'ling
<View> hech qachon skroll qilmaydi. Bu boshlovchilarning eng ko'p uchraydigan chalkashligi: "kodim to'g'ri, lekin pastdagi tugmaga yetolmayapman". Sababi β element <View> ichida, <ScrollView> ichida emas.
<ScrollView> β skroll qilinadigan konteyner¶
Yechim oddiy: <View> o'rniga <ScrollView> ishlatamiz. U react-native dan import qilinadi va ichidagi hamma narsani skroll qilinadigan qiladi.
// app/index.tsx β ScrollView bilan: endi skroll ishlaydi!
import { ScrollView, Text } from 'react-native';
export default function Index() {
return (
<ScrollView style={{ flex: 1, padding: 20 }}>
{Array.from({ length: 30 }).map((_, i) => (
<Text key={i} style={{ fontSize: 18, marginBottom: 16 }}>
Bu {i + 1}-qator matn.
</Text>
))}
</ScrollView>
);
}
Atigi bitta so'zni o'zgartirdik β View o'rniga ScrollView β va endi barmoq bilan tortib hamma 30 qatorni ko'ra olasiz. Ajoyib!
style va contentContainerStyle β MUHIM farq¶
<ScrollView> da ikkita alohida stil propi bor va ularni chalkashtirish β juda keng tarqalgan xato. Keling, farqni aniq tushunib olaylik.
styleβ bu ScrollView'ning o'zining (ya'ni "deraza"ning) stili. Uning balandligi, foni, chegarasi shu yerda.contentContainerStyleβ bu ScrollView ichidagi kontentning (ya'ni "uzun varaq"ning) stili. Ichkipadding,gap,alignItemsshu yerda yoziladi.
Hayotiy o'xshatish.
styleβ derazaning ramkasi va o'lchami.contentContainerStyleβ deraza ortidagi varaqning ichki tartibi (matn chetidan qancha bo'shliq qoldirish, qatorlar orasi qancha bo'lishi).
// padding va gap'ni contentContainerStyle ga beramiz β style ga emas!
import { ScrollView, Text, StyleSheet } from 'react-native';
export default function Index() {
return (
<ScrollView
style={styles.skroll} // deraza: flex, fon
contentContainerStyle={styles.ichi} // varaq ichi: padding, gap
>
<Text style={styles.matn}>Birinchi blok</Text>
<Text style={styles.matn}>Ikkinchi blok</Text>
<Text style={styles.matn}>Uchinchi blok</Text>
</ScrollView>
);
}
const styles = StyleSheet.create({
skroll: { flex: 1, backgroundColor: '#f8fafc' },
ichi: { padding: 16, gap: 12 },
matn: { fontSize: 16, color: '#1e293b' },
});
Eng ko'p uchraydigan xato
padding, gap, alignItems, justifyContent kabi ichki tartib stillarini style ga yozsangiz, ular kutilgandek ishlamasligi mumkin (ayniqsa justifyContent). Ichki kontentni joylash uchun doim contentContainerStyle ishlating. flex: 1 esa aksincha β style ga yoziladi.
horizontal β yon tomonga skroll¶
Sukut bo'yicha ScrollView vertikal (yuqori-past) skroll qiladi. horizontal propini qo'shsangiz β gorizontal (chap-o'ng) skrollga aylanadi. Bu rasm galereyasi, "stories", toifa teglari uchun juda qulay.
// Gorizontal rang galereyasi β yon tomonga skroll
import { ScrollView, View, StyleSheet } from 'react-native';
export default function Galereya() {
const ranglar = ['#0ea5e9', '#6366f1', '#16a34a', '#f59e0b', '#dc2626'];
return (
<ScrollView
horizontal // yon tomonga skroll
showsHorizontalScrollIndicator={false} // pastdagi skroll chizig'ini yashir
contentContainerStyle={{ gap: 12, padding: 16 }}
>
{ranglar.map((rang) => (
<View key={rang} style={[styles.karta, { backgroundColor: rang }]} />
))}
</ScrollView>
);
}
const styles = StyleSheet.create({
karta: { width: 120, height: 160, borderRadius: 16 },
});
Skroll chizig'ini yashirish¶
ScrollView yon tomonida (yoki pastida) ingichka skroll ko'rsatkichi paydo bo'ladi. Uni yashirish uchun:
showsVerticalScrollIndicator={false}β vertikal chiziqni yashiradi.showsHorizontalScrollIndicator={false}β gorizontal chiziqni yashiradi.
Bu ko'pincha dizayn toza ko'rinishi uchun ishlatiladi.
refreshControl β "tortib yangilash"¶
Mobil ilovalarda mashhur naqsh bor: ro'yxatni pastga tortsangiz, u yangilanadi (yangi xabarlar, postlar yuklanadi). Bu "pull to refresh" deb ataladi. ScrollView'ga refreshControl propi orqali qo'shiladi.
// Tortib yangilash (pull to refresh)
import { useState } from 'react';
import { ScrollView, Text, RefreshControl } from 'react-native';
export default function Royxat() {
const [yangilanmoqda, setYangilanmoqda] = useState(false);
const yangila = () => {
setYangilanmoqda(true);
// bu yerda odatda API'dan yangi ma'lumot olinadi
setTimeout(() => setYangilanmoqda(false), 1500); // soxta yuklash
};
return (
<ScrollView
refreshControl={
<RefreshControl refreshing={yangilanmoqda} onRefresh={yangila} />
}
>
<Text style={{ fontSize: 16, padding: 20 }}>
Ekranni pastga torting β yangilanadi.
</Text>
</ScrollView>
);
}
refreshing β hozir yangilanyaptimi (spinner ko'rinadimi); onRefresh β foydalanuvchi tortganda chaqiriladigan funksiya. Ish tugagach refreshing ni yana false qilish shart, aks holda spinner aylanaverib qoladi.
ScrollView vs FlatList β qachon qaysi?¶
Bu β bobning eng muhim tushunchalaridan biri. ScrollView qulay, lekin uning jiddiy cheklovi bor:
<ScrollView> ichidagi BARCHA elementlarni darhol render qiladi β hatto ekrandan tashqarida, hali ko'rinmayotganlarini ham. 20-30 element uchun bu yaxshi. Lekin 1000 ta element bo'lsa? Telefon hammasini bir vaqtda chizishga urinib, sekinlashadi yoki "qotadi".
Bunday holatlar uchun <FlatList> bor (uni keyingi, 08-bobda batafsil o'rganamiz). FlatList faqat hozir ekranda ko'rinadigan elementlarni render qiladi; pastga skroll qilsangiz, yangilarini chizib, yuqoridagi ko'rinmaydiganlarini "tashlab yuboradi". Shuning uchun u uzun ro'yxatlarda juda tez ishlaydi.
Oddiy qoida
- Elementlar soni oz va aniq bo'lsa (masalan profil sahifasi, sozlamalar, forma) β
ScrollView. - Elementlar ko'p, cheksiz yoki noma'lum sonda bo'lsa (xabarlar lentasi, mahsulotlar ro'yxati, izohlar) β
FlatList.
Ichma-ich qo'ymang
Vertikal ScrollView ichiga vertikal FlatList (yoki teskarisini) joylash sekinlik va ogohlantirishlarga olib keladi, chunki ikkalasi ham balandlikni cheksiz deb hisoblaydi. Agar kerak bo'lsa, FlatList'ning o'z ListHeaderComponent / ListFooterComponent proplaridan foydalaning (08-bobda).
SafeAreaView β kontent o'yiq ostida qolmasin¶
Endi zamonaviy telefonlarning eng muhim muammosiga keldik. Hozirgi telefonlarda ekran chetlari to'liq bilan band: yuqorida notch (kamera/dinamik orol o'yig'i), pastda esa bosh sahifa chizig'i (home indicator) bor.
Agar kontentingizni hech qanday himoyasiz to'g'ridan-to'g'ri ekran chetiga joylasangiz, sarlavhangiz notch ostiga, pastdagi tugmangiz esa bosh sahifa chizig'i ostiga tushib qolib, ko'rinmay yoki bosib bo'lmaydigan holga keladi.
Hayotiy o'xshatish. Telefon ekrani β devordagi suratga o'xshaydi, lekin uning yuqori burchaklarida (notch) va pastida (chiziq) "teshik"lar bor. Agar muhim yozuvni aynan shu teshiklar ustiga yozsangiz, uni o'qib bo'lmaydi. Xavfsiz hudud (safe area) β teshiklardan xoli, "toza" markaziy zona. SafeAreaView kontentni mana shu toza zonaga joylaydi.
To'g'ri import β bu juda muhim!¶
SafeAreaView ni react-native-safe-area-context paketidan import qiling, React Native'ning o'zidagi eski SafeAreaView dan EMAS.
// TO'G'RI β zamonaviy, iOS va Android'da to'g'ri ishlaydi:
import { SafeAreaView } from 'react-native-safe-area-context';
// XATO β RN'ning eski o'rnatilgani (faqat iOS, eskirgan):
// import { SafeAreaView } from 'react-native';
Nega aynan shu paket?
RN'ning ichki SafeAreaView faqat iOS'da ishlaydi va Android notch'larini hisobga olmaydi. react-native-safe-area-context esa ikkala platformada ham qurilmaning haqiqiy o'lchamlarini biladi. Expo loyihalarida bu paket allaqachon o'rnatilgan β qo'shimcha o'rnatish shart emas.
Foydalanish o'ta oddiy β eng tashqi <View> ni <SafeAreaView> ga almashtiring:
// app/index.tsx β kontent xavfsiz hududda
import { SafeAreaView } from 'react-native-safe-area-context';
import { Text } from 'react-native';
export default function Index() {
return (
<SafeAreaView style={{ flex: 1 }}>
<Text style={{ fontSize: 20, padding: 20 }}>
Salom! Men o'yiq ostida emasman.
</Text>
</SafeAreaView>
);
}
style={{ flex: 1 }} β SafeAreaView butun ekranni egallashi uchun kerak. U avtomatik ravishda yuqoridan va pastdan kerakli bo'shliqni qoldiradi.
useSafeAreaInsets() β aniq o'lchamlar kerak bo'lganda¶
Ba'zan kontentni SafeAreaView ichiga butunlay o'rab qo'yish o'rniga, faqat bir tomondan bo'shliq qoldirishni xohlaysiz (masalan, faqat yuqoridan, fon esa to'liq ekranga yoyilishi kerak). Buning uchun useSafeAreaInsets() hookidan foydalanamiz. U sizga to'rt tomondagi xavfsiz bo'shliqlarni raqam sifatida beradi.
// useSafeAreaInsets bilan moslashuvchan joylash
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { View, Text } from 'react-native';
export default function Ekran() {
const insets = useSafeAreaInsets();
// insets.top, insets.bottom, insets.left, insets.right β barchasi raqam (dp)
return (
<View style={{ flex: 1, paddingTop: insets.top, backgroundColor: '#0ea5e9' }}>
<Text style={{ fontSize: 18, color: '#fff', padding: 16 }}>
Yuqori bo'shliq: {insets.top} (notch balandligi)
</Text>
</View>
);
}
Bu yerda ko'k fon butun ekranga (notch ortiga ham) yoyiladi, lekin matn paddingTop: insets.top tufayli notch ostiga tushmaydi. Bu naqsh β rangli sarlavha (header) yasashda juda foydali.
Qaysi birini tanlash?
- Oddiy holatlar uchun β
<SafeAreaView style={{ flex: 1 }}>(oson, tez). - Fonni chetga yoyib, faqat matnni himoya qilish kerak bo'lsa β
useSafeAreaInsets().
SafeAreaProvider β ildizda kerak¶
SafeAreaView va useSafeAreaInsets() ishlashi uchun, ilovaning eng yuqorisida SafeAreaProvider bo'lishi kerak. U xavfsiz hudud o'lchamlarini butun ilovaga "tarqatadi".
import { SafeAreaProvider } from 'react-native-safe-area-context';
export default function App() {
return (
<SafeAreaProvider>
{/* butun ilova shu yerda */}
</SafeAreaProvider>
);
}
Yaxshi xabar
Agar Expo Router ishlatayotgan bo'lsangiz (bu kitobda biz uni ishlatamiz β 14-bobdan boshlab), SafeAreaProvider avtomatik sozlangan. Siz uni qo'lda qo'shishingiz shart emas β to'g'ridan-to'g'ri SafeAreaView va useSafeAreaInsets() dan foydalanaverasiz.
StatusBar β yuqoridagi soat/batareya zonasi¶
Status bar β telefon ekranining eng yuqorisidagi, soat, batareya va signal ko'rsatadigan tor chiziq. Ba'zan u oq (och) fonda yaxshi ko'rinadi, ba'zan esa to'q fon kerak. RN'da uni boshqarish uchun expo-status-bar paketidagi StatusBar komponentidan foydalanamiz.
style propi uchta qiymat oladi:
"auto"β tizimga moslashadi (yorug' rejimda qora matn, qorong'i rejimda oq matn). Ko'p hollarda eng yaxshi tanlov."dark"β soat/batareya qora rangda (och fon uchun)."light"β soat/batareya oq rangda (to'q fon uchun).
Hayotiy o'xshatish. Status bar matnini fonga moslang: oq qog'ozga oq qalam bilan yozsangiz hech narsa ko'rinmaydi. To'q fon ustiga
"light", och fon ustiga"dark"qo'ying β shunda soat va batareya doim aniq ko'rinadi.
Ikki xil StatusBar bor
react-native da ham StatusBar bor, lekin Expo loyihalarida expo-status-bar dagisini ishlating β u soddaroq va Expo bilan yaxshiroq ishlaydi. Importga e'tibor bering: import { StatusBar } from 'expo-status-bar';.
Image β chuqurroq (06-bobdan davom)¶
06-bobda Image bilan tanishgandik. Endi uni chuqurroq ko'ramiz, chunki skroll qilinadigan sahifalarda rasmlar ko'p uchraydi.
source β rasm qayerdan keladi?¶
Rasmning ikki manbasi bor:
- Internetdan (uri):
source={{ uri: '...' }}β obyekt ichidaurikaliti. O'lcham berish SHART, aks holda rasm ko'rinmaydi (RN internet rasmining o'lchamini oldindan bilmaydi). - Loyiha ichidan (require):
source={require('./rasm.png')}β bunda RN o'lchamni o'zi biladi, lekin xohlasangiz baribir o'lcham bera olasiz.
import { Image } from 'react-native';
// Internetdan β o'lcham SHART
<Image
source={{ uri: 'https://picsum.photos/300' }}
style={{ width: 200, height: 200, borderRadius: 12 }}
/>
// Loyiha ichidan
<Image
source={require('../assets/images/icon.png')}
style={{ width: 80, height: 80 }}
/>
resizeMode β rasm ramkaga qanday sig'sin?¶
Rasm bilan unga ajratilgan ramka (width/height) o'lchamlari mos kelmasa, resizeMode rasm qanday joylashishini hal qiladi:
'cover'(default) β rasm ramkani to'liq to'ldiradi, kerak bo'lsa chetlari kesiladi. Nisbat saqlanadi. (Profil rasmlari uchun ideal.)'contain'β rasm ramkaga butunligicha sig'adi, hech narsa kesilmaydi, lekin bo'sh joy qolishi mumkin. Nisbat saqlanadi.'stretch'β rasm ramkani to'ldirish uchun cho'ziladi, nisbat buziladi (odatda chiroyli emas).
<Image
source={{ uri: 'https://picsum.photos/400' }}
style={{ width: 200, height: 120, borderRadius: 8 }}
resizeMode="cover" // ramkani to'ldiradi, ortig'i kesiladi
/>
Hayotiy o'xshatish.
coverβ suratni ramkaga "to'ldirib", chetlarini qaychilab joylash.containβ suratni butunligicha ramka ichiga "joylash", atrofida oq haoshiya qolsa qolaveradi.stretchβ suratni rezina kabi cho'zib ramkaga moslash (odam yuzlari "yoyilib" ketadi β shuning uchun kamdan-kam ishlatiladi).
expo-image β zamonaviy, tez alternativa¶
Katta yoki ko'p rasmli ilovalarda RN'ning oddiy Image o'rniga expo-image ni ishlatish tavsiya etiladi. U tezroq, rasmlarni avtomatik keshlaydi (ikkinchi marta darhol ko'rinadi) va rasm yuklanayotganda silliq o'tish (transition) beradi.
import { Image } from 'expo-image';
<Image
source="https://picsum.photos/400" // to'g'ridan-to'g'ri satr ham mumkin
style={{ width: 200, height: 120 }}
contentFit="cover" // RN'dagi resizeMode'ning ekvivalenti
transition={300} // yuklanishda silliq paydo bo'lish (ms)
/>
Farqni unutmang
expo-image da resizeMode emas, contentFit ishlatiladi (qiymatlari deyarli bir xil: 'cover', 'contain' va h.k.). Expo loyihalarida expo-image ko'pincha oldindan o'rnatilgan bo'ladi.
KeyboardAvoidingView β klaviatura inputni to'smasin¶
Yana bir keng tarqalgan muammo: ekran pastidagi TextInput ni bossangiz, klaviatura ochiladi va aynan shu inputni to'sib qo'yadi. Foydalanuvchi nima yozayotganini ko'rmaydi β bu yomon tajriba.
Yechim β react-native dagi KeyboardAvoidingView. U klaviatura ochilganda kontentni avtomatik yuqoriga suradi, shunda input ko'rinib turadi.
// Klaviatura inputni to'smaydigan forma
import { useState } from 'react';
import {
KeyboardAvoidingView,
ScrollView,
TextInput,
Platform,
StyleSheet,
} from 'react-native';
export default function Forma() {
const [matn, setMatn] = useState('');
return (
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<ScrollView contentContainerStyle={{ flexGrow: 1, justifyContent: 'flex-end' }}>
<TextInput
value={matn}
onChangeText={setMatn}
placeholder="Bu yerga yozing..."
style={styles.input}
/>
</ScrollView>
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
input: {
borderWidth: 1, borderColor: '#cbd5e1',
borderRadius: 10, padding: 12, margin: 16, fontSize: 16,
},
});
Eng muhim qism β behavior propi. U iOS va Android'da har xil ishlaydi:
iOS va Android farqi
iOS'da behavior="padding" eng silliq natija beradi; Android'da esa ko'pincha "height" (yoki umuman shart emas, chunki Android'da klaviatura odatda kontentni o'zi suradi). Platform.OS ni tekshirib, har platformaga mosini berish β eng ishonchli yo'l. Platform ni react-native dan import qilishni unutmang.
To'liq misol: skroll qilinadigan profil sahifasi¶
Endi shu bobdagi hamma narsani bitta ekranda birlashtiramiz: SafeAreaView (xavfsiz hudud) + StatusBar (yuqori zona) + ScrollView (uzun kontent) + rasm + ko'p matn + tortib yangilash. Bu kod jonli loyihada tsc bilan tekshirilgan.
// app/profil.tsx β to'liq profil sahifasi
import { useState } from 'react';
import {
ScrollView,
View,
Text,
Image,
Pressable,
RefreshControl,
StyleSheet,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { StatusBar } from 'expo-status-bar';
export default function ProfilSahifasi() {
const [yangilanmoqda, setYangilanmoqda] = useState(false);
const yangila = () => {
setYangilanmoqda(true);
setTimeout(() => setYangilanmoqda(false), 1500); // soxta yuklash
};
return (
<SafeAreaView style={styles.ekran}>
{/* och fon β soat/batareya qora bo'lsin */}
<StatusBar style="dark" />
<ScrollView
contentContainerStyle={styles.kontent}
showsVerticalScrollIndicator={false}
refreshControl={
<RefreshControl refreshing={yangilanmoqda} onRefresh={yangila} />
}
>
{/* profil rasmi β dumaloq */}
<Image
source={{ uri: 'https://i.pravatar.cc/200' }}
style={styles.avatar}
/>
<Text style={styles.ism}>Oqil Imomnazarov</Text>
<Text style={styles.bio}>React Native dasturchisi</Text>
{/* uzun matn β skroll kerak bo'ladi */}
{Array.from({ length: 20 }).map((_, i) => (
<Text key={i} style={styles.paragraf}>
Bu {i + 1}-qator. ScrollView ichida ko'p matn bemalol skroll qilinadi.
</Text>
))}
<Pressable style={styles.tugma}>
<Text style={styles.tugmaMatn}>Profilni tahrirlash</Text>
</Pressable>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
ekran: { flex: 1, backgroundColor: '#f8fafc' },
kontent: { padding: 20, gap: 10, alignItems: 'center' },
avatar: { width: 120, height: 120, borderRadius: 60 }, // radius = yarmi -> dumaloq
ism: { fontSize: 22, fontWeight: '700', color: '#1e293b' },
bio: { fontSize: 15, color: '#475569' },
paragraf: { fontSize: 14, color: '#475569', alignSelf: 'stretch' },
tugma: {
backgroundColor: '#4f46e5', paddingVertical: 12,
paddingHorizontal: 28, borderRadius: 10, marginTop: 12,
},
tugmaMatn: { color: '#fff', fontWeight: '600' },
});
Diqqat qiling:
SafeAreaViewbutun ekranni o'raydi β kontent notch va pastki chiziq ostiga tushmaydi.StatusBar style="dark"β fonimiz och, shuning uchun soat/batareya qora.ScrollViewuzun matnni skroll qilinadigan qiladi,refreshControltortib yangilashni qo'shadi.contentContainerStyleichidapadding,gap,alignItemsβ chunki bular ichki kontent stillari.borderRadius: 60(kenglikning yarmi) bilan rasm dumaloq bo'ladi.
Tekshirib ko'ring
Bu kodni app/profil.tsx ga joylab, telefoningizda oching. Ekranni pastga tortib yangilash spinnerini, so'ng yuqoriga skroll qilib hamma matnni ko'ring. Sarlavha notch ostiga tushyaptimi? Yo'q bo'lsa β SafeAreaView ishlayapti, demak!
Xulosa¶
<View>skroll qilmaydi β kontent ekrandan uzun bo'lsa<ScrollView>ishlating ("uzun varaq" o'xshatishi).- ScrollView'da
style= konteynerning o'zi (flex, fon),contentContainerStyle= ichki kontent (padding, gap, alignItems). Bularni chalkashtirmang. horizontalβ yon tomonga skroll;showsVerticalScrollIndicator={false}β skroll chizig'ini yashiradi;refreshControlβ tortib yangilash.- ScrollView hamma elementni darhol render qiladi β kam/aniq element uchun. Ko'p yoki cheksiz element uchun
FlatList(08-bob). SafeAreaViewkontentni notch va pastki chiziqdan himoyalaydi.react-native-safe-area-contextdan import qiling (RN'ning o'zidagidan emas). Aniqlik kerak bo'lsa βuseSafeAreaInsets().- Expo Router
SafeAreaProviderni avtomatik beradi β qo'lda qo'shish shart emas. StatusBar(expo-status-bardan) yuqoridagi soat/batareya rangini boshqaradi:"auto"/"light"/"dark".Image:uriuchun o'lcham SHART;resizeMode('cover'/'contain'/'stretch'); zamonaviy/tez alternativa βexpo-image(contentFit, kesh).KeyboardAvoidingViewklaviatura ochilganda inputni yuqoriga surib, to'silishdan saqlaydi:behavior={Platform.OS === 'ios' ? 'padding' : 'height'}.
Amaliy mashqlar¶
-
Skroll qilinadigan profil sahifasi. Yuqoridagi to'liq misolni o'z loyihangizda terib, telefoningizda oching. Matn qatorlari sonini 5 taga kamaytiring β skroll yo'qoladimi? Endi 50 taga oshiring β ScrollView'ni
FlatListbilan almashtirmasdan, sekinlashish sezilyaptimi? (Keyingi bobda buni FlatList bilan hal qilamiz.) -
Gorizontal rasm galereyasi.
horizontalScrollView yasab, ichiga kamida 6 ta rasmni (expo-imageyoki oddiyImage,uribilan, masalanhttps://picsum.photos/200?random=1,...random=2, ...) yon tomonga skroll qilinadigan qilib joylang. Rasmlar orasigagapqo'ying va skroll chizig'ini yashiring. Maslahat: rasmlarni massivdan.map()bilan chiqaring. -
SafeArea bilan to'g'ri joylashtirish. Bir ekran yasang: yuqorida rangli (to'q ko'k) header ichida oq sarlavha, ostida esa oq fonli kontent bo'lsin. Header rangi ekranning eng tepasiga (notch ortiga) yoyilsin, lekin sarlavha matni notch ostiga tushmasin. Maslahat:
useSafeAreaInsets()vapaddingTop: insets.topdan foydalaning.StatusBar styleni to'q header'ga moslang ("light"). -
Klaviatura sinovi. Ekran pastida
TextInputjoylashtiring va uniKeyboardAvoidingViewichiga oling. Telefonda inputni bosing β klaviatura uni to'syaptimi?behaviorni o'zgartirib ("padding"β"height") iOS va Android'da farqni kuzating. Maslahat:Platform.OSni vaqtincha bitta qiymatga "majburlab" qo'yib, ikkala holatni ham sinab ko'ring. -
Tortib yangilash (qiyinroq). ScrollView'ga
refreshControlqo'shing vaonRefreshchaqirilganda ekranda ko'rsatiladigan tasodifiy sonni (Math.random()) yangilang. Spinner 1.5 soniyadan keyin yo'qolib, yangi son ko'rinishiga ishonch hosil qiling. (Bu naqshni 17-bobda haqiqiy API bilan bog'laymiz.)
β¬ οΈ Oldingi: 06 β Input va tugmalar Β· π Kitob boshi Β· Keyingi: 08 β Ro'yxatlar: FlatList β‘οΈ