1-2 bo'lim mashqlari — profil kartasi
Qanday ishlash kerak
Siz Expo loyihasini yaratishni, View, Text, Image, ScrollView, TextInput, Pressable, Modal, Alert va Switch ni bilasiz. Endi ularni birlashtirib, haqiqiy ekranlar yasaymiz.
- Har bir mashqni avval o'zingiz bajaring — kamida 15 daqiqa
- Telefonda sinab ko'ring — emulyatorda emas, haqiqiy qurilmada
- Keyin yechim bilan solishtiring
1-mashq: Profil kartasi ⭐
Quyidagi ekranni yasang:
- Yumaloq avatar (tarmoqdagi rasm, 100×100)
- Ism (katta, qalin), kasb (kulrang)
- Uchta statistika yonma-yon: "Postlar 128", "Obunachilar 2.4K", "Obunalar 310"
- "Obuna bo'lish" tugmasi — bosilganda "Obunasiz" ga o'zgaradi va rangi almashadi
Yechim
import { useState } from 'react';
import { View, Text, Image, Pressable, StyleSheet } from 'react-native';
const statlar = [
{ nom: 'Postlar', qiymat: '128' },
{ nom: 'Obunachilar', qiymat: '2.4K' },
{ nom: 'Obunalar', qiymat: '310' },
];
export default function Profil() {
const [obuna, setObuna] = useState(false);
return (
<View style={styles.ekran}>
<Image source={{ uri: 'https://i.pravatar.cc/200?img=12' }} style={styles.avatar} />
<Text style={styles.ism}>Aziz Karimov</Text>
<Text style={styles.kasb}>React Native dasturchi</Text>
<View style={styles.statlar}>
{statlar.map((s) => (
<View key={s.nom} style={styles.stat}>
<Text style={styles.statQiymat}>{s.qiymat}</Text>
<Text style={styles.statNom}>{s.nom}</Text>
</View>
))}
</View>
<Pressable
onPress={() => setObuna(!obuna)}
style={({ pressed }) => [
styles.tugma,
obuna && styles.tugmaObuna,
pressed && { opacity: 0.8 },
]}
>
<Text style={[styles.tugmaMatn, obuna && { color: '#0284c7' }]}>
{obuna ? 'Obunasiz' : "Obuna bo'lish"}
</Text>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
ekran: { flex: 1, alignItems: 'center', paddingTop: 80, backgroundColor: 'white' },
avatar: { width: 100, height: 100, borderRadius: 50, marginBottom: 12 },
ism: { fontSize: 22, fontWeight: '700' },
kasb: { fontSize: 15, color: '#64748b', marginTop: 4 },
statlar: { flexDirection: 'row', gap: 32, marginVertical: 24 },
stat: { alignItems: 'center' },
statQiymat: { fontSize: 18, fontWeight: '700' },
statNom: { fontSize: 13, color: '#64748b' },
tugma: { backgroundColor: '#0284c7', paddingVertical: 12, paddingHorizontal: 40, borderRadius: 10 },
tugmaObuna: { backgroundColor: 'white', borderWidth: 1, borderColor: '#0284c7' },
tugmaMatn: { color: 'white', fontWeight: '600', fontSize: 16 },
});
borderRadius = kenglikning yarmi → doira. flexDirection: 'row' — elementlar yonma-yon (14-darsda batafsil).
2-mashq: Kirish formasi ⭐⭐
- Email va parol maydonlari — to'g'ri
keyboardType,autoCapitalize,autoComplete - Parolni ko'rsatish/yashirish ikonkasi
- Klaviaturadagi "Keyingi" email dan parolga o'tkazsin, "Tayyor" — formani yuborsin
- "Kirish" tugmasi: email yoki parol bo'sh bo'lsa —
disabled - Bosilganda 1.5 soniya
ActivityIndicator, keyinAlert: "Xush kelibsiz, {email}"
Yechim
import { useRef, useState } from 'react';
import { View, Text, TextInput, Pressable, ActivityIndicator, Alert, StyleSheet } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
export default function Kirish() {
const [email, setEmail] = useState('');
const [parol, setParol] = useState('');
const [korinsin, setKorinsin] = useState(false);
const [yuklanmoqda, setYuklanmoqda] = useState(false);
const parolRef = useRef<TextInput>(null);
const tayyor = email.trim() !== '' && parol !== '';
async function kirish() {
if (!tayyor || yuklanmoqda) return;
setYuklanmoqda(true);
await new Promise((r) => setTimeout(r, 1500)); // server so'rovi o'rniga
setYuklanmoqda(false);
Alert.alert('Xush kelibsiz', email.trim());
}
return (
<View style={styles.ekran}>
<Text style={styles.sarlavha}>Kirish</Text>
<TextInput
style={styles.input}
placeholder="Email"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
autoComplete="email"
returnKeyType="next"
onSubmitEditing={() => parolRef.current?.focus()}
/>
<View style={styles.parolQator}>
<TextInput
ref={parolRef}
style={[styles.input, { flex: 1, borderWidth: 0 }]}
placeholder="Parol"
value={parol}
onChangeText={setParol}
secureTextEntry={!korinsin}
autoComplete="password"
returnKeyType="done"
onSubmitEditing={kirish}
/>
<Pressable onPress={() => setKorinsin(!korinsin)} hitSlop={10} style={{ paddingHorizontal: 12 }}>
<Ionicons name={korinsin ? 'eye-off-outline' : 'eye-outline'} size={22} color="#64748b" />
</Pressable>
</View>
<Pressable
onPress={kirish}
disabled={!tayyor || yuklanmoqda}
style={({ pressed }) => [
styles.tugma,
(!tayyor || yuklanmoqda) && { opacity: 0.5 },
pressed && { opacity: 0.8 },
]}
>
{yuklanmoqda ? <ActivityIndicator color="white" /> : <Text style={styles.tugmaMatn}>Kirish</Text>}
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
ekran: { flex: 1, justifyContent: 'center', padding: 24, gap: 14, backgroundColor: 'white' },
sarlavha: { fontSize: 28, fontWeight: '800', marginBottom: 12 },
input: { borderWidth: 1, borderColor: '#cbd5e1', borderRadius: 10, padding: 14, fontSize: 16 },
parolQator: { flexDirection: 'row', alignItems: 'center', borderWidth: 1, borderColor: '#cbd5e1', borderRadius: 10 },
tugma: { backgroundColor: '#0284c7', padding: 16, borderRadius: 12, alignItems: 'center', minHeight: 54, justifyContent: 'center' },
tugmaMatn: { color: 'white', fontSize: 16, fontWeight: '600' },
});
3-mashq: Sozlamalar ekrani ⭐⭐
ScrollViewichida 3 ta guruh: "Hisob", "Bildirishnomalar", "Boshqa"- "Bildirishnomalar" guruhida 3 ta
Switch(Push, Email, SMS) — har biri o'z holati bilan - "Boshqa" guruhida "Hisobni o'chirish" — qizil matn, bosilganda tasdiqlovchi
Alert(destructive) - Har bir band —
Pressablevaandroid_ripple
Yechim
import { useState } from 'react';
import { ScrollView, View, Text, Pressable, Switch, Alert, StyleSheet } from 'react-native';
function Band({ matn, onPress, xavfli }: { matn: string; onPress?: () => void; xavfli?: boolean }) {
return (
<Pressable onPress={onPress} android_ripple={{ color: '#e2e8f0' }}
style={({ pressed }) => [styles.band, pressed && { backgroundColor: '#f1f5f9' }]}>
<Text style={[styles.bandMatn, xavfli && { color: '#dc2626' }]}>{matn}</Text>
</Pressable>
);
}
export default function Sozlamalar() {
const [sozlama, setSozlama] = useState({ push: true, email: false, sms: true });
const almashtir = (k: keyof typeof sozlama) => setSozlama((s) => ({ ...s, [k]: !s[k] }));
return (
<ScrollView style={{ flex: 1, backgroundColor: '#f1f5f9' }} contentContainerStyle={{ padding: 16, gap: 24 }}>
<View style={styles.guruh}>
<Text style={styles.guruhNom}>HISOB</Text>
<Band matn="Profilni tahrirlash" onPress={() => {}} />
<Band matn="Parolni o'zgartirish" onPress={() => {}} />
</View>
<View style={styles.guruh}>
<Text style={styles.guruhNom}>BILDIRISHNOMALAR</Text>
{(['push', 'email', 'sms'] as const).map((k) => (
<View key={k} style={[styles.band, styles.qator]}>
<Text style={styles.bandMatn}>{k.toUpperCase()}</Text>
<Switch value={sozlama[k]} onValueChange={() => almashtir(k)} />
</View>
))}
</View>
<View style={styles.guruh}>
<Text style={styles.guruhNom}>BOSHQA</Text>
<Band
matn="Hisobni o'chirish"
xavfli
onPress={() =>
Alert.alert("Hisobni o'chirish", "Barcha ma'lumotlaringiz o'chiriladi.", [
{ text: 'Bekor qilish', style: 'cancel' },
{ text: "O'chirish", style: 'destructive', onPress: () => console.log("o'chirildi") },
])
}
/>
</View>
</ScrollView>
);
}
const styles = StyleSheet.create({
guruh: { backgroundColor: 'white', borderRadius: 12, overflow: 'hidden' },
guruhNom: { fontSize: 12, color: '#64748b', padding: 12, paddingBottom: 4, fontWeight: '600' },
band: { paddingVertical: 14, paddingHorizontal: 16 },
qator: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' },
bandMatn: { fontSize: 16 },
});
overflow: 'hidden' — guruhning yumaloq burchaklari ichidagi bandlarni ham qirqadi.
O'zingizni tekshiring
Viewichiga to'g'ridan-to'g'ri matn yozsa nima bo'ladi?- Tarmoqdagi rasm nima uchun ko'rinmasligi mumkin?
ScrollViewni qachon ishlatmaslik kerak?- Email maydoni uchun qaysi uchta xususiyat muhim?
- Tugma ikki marta bosilishining oldini qanday olasiz?
AlertvaModalfarqi nima?
Keyingi bo'lim
3-bo'lim: Stil va layout — StyleSheet va CSS farqlari, Flexbox, turli ekran o'lchamlari, qorong'i rejim va safe area.