Klaviatura — KeyboardAvoidingView, fokus, yopish
Muammodan boshlaylik
Kirish ekrani: pastda "Kirish" tugmasi. Foydalanuvchi parol maydoniga bosadi — klaviatura chiqadi va parol maydonini ham, tugmani ham yopib qo'yadi. U nima yozayotganini ko'rmaydi va tugmaga yetolmaydi. Klaviaturani yopish uchun esa hech qanday yo'l yo'q.
Mobil ilovalarda eng ko'p shikoyat qilinadigan muammolardan biri. Yechim — bir nechta oddiy usul.
KeyboardAvoidingView
Klaviatura chiqqanda kontentni yuqoriga siljitadi:
import { KeyboardAvoidingView, Platform, ScrollView } from 'react-native';
export default function Kirish() {
return (
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
<ScrollView
contentContainerStyle={{ flexGrow: 1, justifyContent: 'center', padding: 24, gap: 14 }}
keyboardShouldPersistTaps="handled"
>
<TextInput placeholder="Email" style={styles.input} />
<TextInput placeholder="Parol" secureTextEntry style={styles.input} />
<Tugma matn="Kirish" onPress={kirish} />
</ScrollView>
</KeyboardAvoidingView>
);
}
behavior |
Nima qiladi |
|---|---|
padding |
Pastga klaviatura balandligicha padding qo'shadi — iOS uchun |
height |
Konteyner balandligini kamaytiradi — Android uchun |
position |
Butun konteynerni siljitadi |
Platformaga qarab behavior — standart naqsh. Android ning o'zi ham ko'pincha oynani klaviaturaga moslaydi (softwareKeyboardLayoutMode — app.json da "resize" standart).
flexGrow: 1 — flex: 1 emas: kontent qisqa bo'lsa ekranni to'ldiradi (markazlash ishlaydi), uzun bo'lsa — aylanadi.
Sarlavha bilan — keyboardVerticalOffset
Stack sarlavhasi bor ekranda kontent biroz kam siljiydi. Tuzatish:
import { useHeaderHeight } from '@react-navigation/elements';
const sarlavha = useHeaderHeight();
<KeyboardAvoidingView behavior="padding" keyboardVerticalOffset={sarlavha} style={{ flex: 1 }}>
Klaviaturani yopish
Bo'sh joyni bosganda
import { Keyboard, Pressable } from 'react-native';
<Pressable style={{ flex: 1 }} onPress={Keyboard.dismiss} accessible={false}>
{/* forma */}
</Pressable>
ScrollView da — surganda yopilish
<ScrollView keyboardDismissMode="on-drag"> {/* iOS: 'interactive' — barmoq bilan tortib */}
keyboardShouldPersistTaps
Klaviatura ochiq paytda tugmani bosasiz — tugma ishlamaydi, faqat klaviatura yopiladi. Ikkinchi bosish kerak. Juda bezovta.
<ScrollView keyboardShouldPersistTaps="handled">
| Qiymat | Klaviatura ochiq paytda bosilganda |
|---|---|
never (standart) |
Faqat klaviatura yopiladi |
handled |
Tugma ishlaydi; bo'sh joy bosilsa — klaviatura yopiladi ✅ |
always |
Har doim bosish ishlaydi, klaviatura yopilmaydi |
Formali har bir ScrollView / FlatList ga — keyboardShouldPersistTaps="handled".
Yuborishda
async function yuborish() {
Keyboard.dismiss();
// ...
}
Klaviatura hodisalari
useEffect(() => {
const ochildi = Keyboard.addListener('keyboardDidShow', (e) => {
console.log('Balandlik:', e.endCoordinates.height);
});
const yopildi = Keyboard.addListener('keyboardDidHide', () => {});
return () => { ochildi.remove(); yopildi.remove(); };
}, []);
Masalan, klaviatura ochiqligida pastki tab panelni yashirish yoki chatda oxirgi xabarga scroll qilish.
Murakkab holatlar: react-native-keyboard-controller
O'rnatilgan KeyboardAvoidingView ning cheklovlari bor: ikki platformada turlicha ishlaydi, animatsiya klaviatura bilan sinxron emas, uzun formalarda fokusdagi maydonga avtomatik scroll yo'q. Professional ilovalarda ko'pincha react-native-keyboard-controller:
npx expo install react-native-keyboard-controller
// app/_layout.tsx
import { KeyboardProvider } from 'react-native-keyboard-controller';
<KeyboardProvider><Stack /></KeyboardProvider>
// Formada
import { KeyboardAwareScrollView } from 'react-native-keyboard-controller';
<KeyboardAwareScrollView bottomOffset={20} contentContainerStyle={{ padding: 16, gap: 14 }}>
{/* 15 ta maydon — fokuslangani har doim klaviatura ustida ko'rinadi */}
</KeyboardAwareScrollView>
- Ikkala platformada bir xil
- Fokusdagi maydonga avtomatik scroll
- Klaviatura bilan sinxron, silliq animatsiya
[!INFO] Bu kutubxona native kod talab qiladi — Expo Go da ishlamasligi mumkin, development build kerak (48-dars). O'rganish bosqichida
KeyboardAvoidingViewyetarli.
Chat ekrani
Chatda xabar yozish maydoni klaviatura bilan birga ko'tarilishi kerak:
<KeyboardAvoidingView style={{ flex: 1 }} behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={useHeaderHeight()}>
<FlatList
data={xabarlar}
inverted // yangi xabarlar pastda, ro'yxat pastdan boshlanadi
keyboardDismissMode="interactive"
keyboardShouldPersistTaps="handled"
renderItem={...}
/>
<XabarPaneli />
</KeyboardAvoidingView>
inverted — ro'yxat teskari: eng yangisi pastda, scroll pastdan boshlanadi. Har qanday chat ilovasining asosi.
Sinash ro'yxati
- Har bir maydonga bosing — u klaviatura ustida ko'rinadimi?
- Klaviatura ochiq paytda tugmani bir marta bosish yetadimi?
- Klaviaturani yopish yo'li bormi?
- Ikkala platformada (iOS va Android klaviaturalari turlicha balandlikda)
- Kichik ekranli telefonda
Nima uchun shunday?
Nima uchun React Native klaviaturani avtomatik hal qilmaydi — brauzer kontentni o'zi siljitadi-ku?
Brauzer bitta sahifani boshqaradi va uni klaviatura ochilganda shunchaki scroll qiladi. Mobil ilova esa ko'pincha scroll siz ekranlardan iborat: flex bilan joylashgan sarlavha, kontent va pastki panel. Qaysi element yuqoriga ko'tarilishi kerak — butun ekranmi, faqat pastki panelmi, yoki ro'yxatmi? Bu dizayn qarori va har bir ekranda boshqacha. Bundan tashqari, iOS va Android klaviaturani butunlay boshqacha boshqaradi. Shuning uchun React Native vositalar beradi, qarorni esa sizga qoldiradi.
Xulosa
Eslab qoling:
KeyboardAvoidingView—behavior: iOS —padding, Android —heightyoki yo'q- Ichida
ScrollView+contentContainerStyle={{ flexGrow: 1 }} - Sarlavha bor bo'lsa —
keyboardVerticalOffset={useHeaderHeight()} keyboardShouldPersistTaps="handled"— tugmalar birinchi bosishda ishlasin- Yopish:
Keyboard.dismiss(),keyboardDismissMode="on-drag" - Murakkab formalar —
react-native-keyboard-controller - Chat —
FlatList inverted - Ikkala platformada sinang
Keyingi dars
24-dars: 3-4 bo'lim mashqlari — kontaktlar ilovasi