Flexbox mobil ekranda — column standart, flex: 1

~20 daq · React Native · Stil va layout

Muammodan boshlaylik

Chat ekrani: tepada sarlavha, o'rtada xabarlar (qolgan barcha joyni egallasin), pastda xabar yozish maydoni va yuborish tugmasi yonma-yon. Ekran o'lchami telefonga qarab har xil.

Vebda buni CSS Grid, position: fixed, calc(100vh - 120px) bilan qilardingiz. React Native da faqat bitta vosita bor — Flexbox. Va u yetarli.


Asosiy farq: column standart

<View>
  <View style={{ width: 50, height: 50, backgroundColor: 'red' }} />
  <View style={{ width: 50, height: 50, backgroundColor: 'green' }} />
  <View style={{ width: 50, height: 50, backgroundColor: 'blue' }} />
</View>

Natija — ustma-ust, yonma-yon emas. React Native da:

Vebda React Native
display block flex — har doim
flexDirection row column
alignContent stretch flex-start
flexShrink 1 0

Mobil ekran tik (vertikal) — shuning uchun elementlar standart holatda tepadan pastga joylashadi. Yonma-yon kerak bo'lsa:

<View style={{ flexDirection: 'row' }}>...</View>

Ikki o'q

flexDirection: 'column'          flexDirection: 'row'
┌──────────┐                     ┌──────────────────────┐
│    ▼     │ ← asosiy o'q        │ ▶ ▶ ▶                │ ← asosiy o'q
│    ▼     │   (justifyContent)  │                      │
│    ▼     │                     └──────────────────────┘
└──────────┘                       ↕ kesishgan o'q (alignItems)
  ↔ kesishgan o'q (alignItems)
  • justifyContent — asosiy o'q bo'ylab
  • alignItems — kesishgan o'q bo'ylab

column da justifyContent — vertikal, row da — gorizontal. Bu eng ko'p chalkashtiriladigan joy.

justifyContent

justifyContent: 'flex-start'      // boshida (standart)
justifyContent: 'center'          // markazda
justifyContent: 'flex-end'        // oxirida
justifyContent: 'space-between'   // chetlarga, oralar teng
justifyContent: 'space-around'
justifyContent: 'space-evenly'

alignItems

alignItems: 'stretch'      // to'liq cho'zilish (standart)
alignItems: 'flex-start'
alignItems: 'center'
alignItems: 'flex-end'

Ekran markazida element:

<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
  <Text>Markazda</Text>
</View>

flex: 1 — eng muhim xususiyat

flex: 1 — "ota konteynerdagi bo'sh joyning hammasini egalla".

<View style={{ flex: 1 }}>                          {/* butun ekran */}
  <View style={{ height: 60, backgroundColor: '#0284c7' }} />   {/* sarlavha — 60 */}
  <View style={{ flex: 1, backgroundColor: '#f1f5f9' }} />      {/* qolgan hammasi */}
  <View style={{ height: 70, backgroundColor: 'white' }} />     {/* pastki panel — 70 */}
</View>

Telefon qanday bo'lmasin — sarlavha 60, pastki panel 70, o'rtadagi kontent — qolgan hamma joy. Chat ekranining asosiy tuzilmasi tayyor.

Nisbatlar

<View style={{ flex: 1, flexDirection: 'row' }}>
  <View style={{ flex: 1, backgroundColor: 'red' }} />    {/* 1/3 */}
  <View style={{ flex: 2, backgroundColor: 'blue' }} />   {/* 2/3 */}
</View>

Bo'sh joy flex qiymatlari nisbatida bo'linadi.

[!WARNING] Eng ko'p uchraydigan xato: ichki elementga flex: 1 berasiz, lekin u ko'rinmaydi. Sababi — otasida flex: 1 (yoki aniq balandlik) yo'q. Ota 0 balandlikda bo'lsa, uning "bo'sh joyi" ham 0. flex: 1 zanjiri ekranning ildizidan boshlanishi kerak.


Chat ekrani — to'liq misol

<View style={{ flex: 1, backgroundColor: 'white' }}>
  {/* Sarlavha */}
  <View style={styles.sarlavha}>
    <Text style={styles.sarlavhaMatn}>Malika</Text>
  </View>

  {/* Xabarlar — qolgan joy */}
  <ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 12, gap: 8 }}>
    <View style={[styles.xabar, styles.boshqa]}><Text>Salom! Buyurtma qachon keladi?</Text></View>
    <View style={[styles.xabar, styles.meniki]}><Text style={{ color: 'white' }}>Ertaga soat 14:00 gacha</Text></View>
  </ScrollView>

  {/* Pastki panel — row */}
  <View style={styles.panel}>
    <TextInput style={styles.input} placeholder="Xabar..." />
    <Pressable style={styles.yuborish}><Ionicons name="send" size={20} color="white" /></Pressable>
  </View>
</View>

const styles = StyleSheet.create({
  sarlavha: { height: 56, justifyContent: 'center', paddingHorizontal: 16, borderBottomWidth: 1, borderColor: '#e2e8f0' },
  sarlavhaMatn: { fontSize: 18, fontWeight: '700' },
  xabar: { padding: 12, borderRadius: 16, maxWidth: '80%' },
  boshqa: { backgroundColor: '#f1f5f9', alignSelf: 'flex-start' },
  meniki: { backgroundColor: '#0284c7', alignSelf: 'flex-end' },
  panel: { flexDirection: 'row', alignItems: 'center', padding: 8, gap: 8, borderTopWidth: 1, borderColor: '#e2e8f0' },
  input: { flex: 1, backgroundColor: '#f1f5f9', borderRadius: 20, paddingHorizontal: 16, paddingVertical: 10, fontSize: 16 },
  yuborish: { width: 44, height: 44, borderRadius: 22, backgroundColor: '#0284c7', justifyContent: 'center', alignItems: 'center' },
});
  • alignSelf — bitta element otaning alignItems ini o'zgartiradi: mening xabarlarim o'ngda, boshqalarniki chapda
  • input da flex: 1 — tugmadan qolgan butun kenglikni egallaydi

Boshqa foydali xususiyatlar

gap — elementlar orasidagi masofa

<View style={{ flexDirection: 'row', gap: 12 }}>...</View>

Har biriga marginRight berib, oxirgisidan olib tashlash shart emas. rowGap, columnGap ham bor.

flexWrap — keyingi qatorga o'tish

<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 8 }}>
  {teglar.map((t) => <View key={t} style={styles.chip}><Text>{t}</Text></View>)}
</View>

Teglar sig'maganda keyingi qatorga tushadi.

Ikki ustunli grid

<View style={{ flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-between' }}>
  {mahsulotlar.map((m) => (
    <View key={m.id} style={{ width: '48%', marginBottom: 12 }}>...</View>
  ))}
</View>

Uzun ro'yxat bo'lsa — FlatList ning numColumns={2} (19-dars).

position: absolute

<View>
  <Image source={...} style={{ width: 60, height: 60, borderRadius: 30 }} />
  <View style={{ position: 'absolute', top: 0, right: 0, width: 16, height: 16, borderRadius: 8, backgroundColor: '#22c55e', borderWidth: 2, borderColor: 'white' }} />
</View>

Avatar ustidagi "onlayn" belgisi. position: 'absolute' — otaga nisbatan (otada position: 'relative' standart, alohida yozish shart emas). position: 'fixed' yo'q.

StyleSheet.absoluteFillObject — { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 } qisqartmasi.


Nima uchun shunday?

Nima uchun React Native da flexDirection standart holatda column?

Vebdagi row standarti — matnli hujjatlar davridan qolgan: so'zlar chapdan o'ngga yoziladi. Mobil ilova esa tik ekranda va asosan vertikal quriladi: sarlavha, kontent, tugmalar — tepadan pastga. React Native jamoasi eng ko'p uchraydigan holatni standart qilib, har bir konteynerga flexDirection: 'column' yozish zaruratini olib tashladi.


Xulosa

Eslab qoling:

  • Hamma narsa flex; flexDirection standart — column
  • justifyContent — asosiy o'q, alignItems — kesishgan o'q
  • flex: 1 — bo'sh joyning hammasi; otasida ham flex: 1 bo'lishi shart
  • Sarlavha (aniq balandlik) + kontent (flex: 1) + pastki panel — ekran asosi
  • alignSelf — bitta elementni boshqacha joylash
  • gap, flexWrap, width: '48%' — ro'yxat va gridlar
  • position: 'absolute' — ustma-ust elementlar; fixed yo'q

Keyingi dars

15-dars: O'lchamlar — useWindowDimensions, foizlar, turli ekranlar