Qorong'i rejim — useColorScheme, mavzu tizimi
Muammodan boshlaylik
Foydalanuvchi kechqurun telefonida qorong'i rejimni yoqdi. Barcha ilovalar qorong'i — sizning ilovangizdan tashqari. Qop-qora xonada oppoq ekran ko'zni qamashtiradi. Yoki yanada yomon: ba'zi tizim elementlari qorong'i bo'ldi, sizning oq fondagi qora matningiz esa qora fondagi qora matnga aylandi.
Bugun qorong'i rejim — "qo'shimcha imkoniyat" emas, kutilgan standart.
1. app.json da yoqish
{
"expo": {
"userInterfaceStyle": "automatic"
}
}
| Qiymat | Ma'nosi |
|---|---|
automatic |
Tizim sozlamasiga qarab (tavsiya) |
light |
Doim yorug' |
dark |
Doim qorong'i |
light bo'lsa — useColorScheme doim 'light' qaytaradi.
2. useColorScheme
import { useColorScheme } from 'react-native';
export default function Ekran() {
const sxema = useColorScheme(); // 'light' | 'dark' | null
const qorongi = sxema === 'dark';
return (
<View style={{ flex: 1, backgroundColor: qorongi ? '#0f172a' : '#ffffff' }}>
<Text style={{ color: qorongi ? '#f1f5f9' : '#0f172a' }}>Salom</Text>
</View>
);
}
Foydalanuvchi tizim sozlamasini o'zgartirsa — hook avtomatik yangilanadi va ekran darhol qayta chiziladi.
Lekin har bir komponentda qorongi ? ... : ... yozish — tez orada tartibsizlikka aylanadi. Kerak — mavzu tizimi.
3. Mavzu tizimi
Ranglarni ma'nosi bo'yicha nomlang
// constants/theme.ts
export const mavzular = {
light: {
fon: '#ffffff',
fonIkkinchi: '#f8fafc',
karta: '#ffffff',
matn: '#0f172a',
matnIkkinchi: '#64748b',
chegara: '#e2e8f0',
asosiy: '#0284c7',
asosiyMatn: '#ffffff',
xato: '#dc2626',
},
dark: {
fon: '#0b1120',
fonIkkinchi: '#0f172a',
karta: '#1e293b',
matn: '#f1f5f9',
matnIkkinchi: '#94a3b8',
chegara: '#334155',
asosiy: '#38bdf8',
asosiyMatn: '#0b1120',
xato: '#f87171',
},
} as const;
export type Mavzu = typeof mavzular.light;
oq, qora emas — fon, matn, karta. Komponent "bu yerga matn rangi" deydi, u qaysi rang ekanini mavzu hal qiladi.
Custom hook
// hooks/useMavzu.ts
import { useColorScheme } from 'react-native';
import { mavzular } from '@/constants/theme';
export function useMavzu() {
const sxema = useColorScheme() ?? 'light';
return mavzular[sxema];
}
Ishlatish
import { useMavzu } from '@/hooks/useMavzu';
export function MahsulotKarta({ nom, narx }: { nom: string; narx: number }) {
const m = useMavzu();
return (
<View style={[styles.karta, { backgroundColor: m.karta, borderColor: m.chegara }]}>
<Text style={[styles.nom, { color: m.matn }]}>{nom}</Text>
<Text style={{ color: m.matnIkkinchi }}>{narx.toLocaleString()} so'm</Text>
</View>
);
}
const styles = StyleSheet.create({
karta: { padding: 16, borderRadius: 12, borderWidth: 1 }, // rangsiz tuzilma
nom: { fontSize: 16, fontWeight: '600' },
});
Naqsh: StyleSheet da — tuzilma (o'lcham, padding, radius), massivning ikkinchi qismida — mavzu ranglari.
Stillarni hook ichida yaratish
Rang ko'p bo'lsa, bu usul tozaroq:
function useStillar() {
const m = useMavzu();
return useMemo(() => StyleSheet.create({
ekran: { flex: 1, backgroundColor: m.fon },
sarlavha: { fontSize: 22, fontWeight: '700', color: m.matn },
izoh: { color: m.matnIkkinchi },
}), [m]);
}
export default function Ekran() {
const s = useStillar();
return <View style={s.ekran}><Text style={s.sarlavha}>Salom</Text></View>;
}
useMemo — stillar faqat mavzu o'zgarganda qayta yaratiladi.
4. Navigatsiya va status bar
Expo Router sarlavhalari va tab panellari ham mavzuga mos bo'lishi kerak:
// app/_layout.tsx
import { ThemeProvider, DarkTheme, DefaultTheme } from '@react-navigation/native';
import { StatusBar } from 'expo-status-bar';
import { useColorScheme } from 'react-native';
export default function RootLayout() {
const sxema = useColorScheme();
return (
<ThemeProvider value={sxema === 'dark' ? DarkTheme : DefaultTheme}>
<Stack />
<StatusBar style="auto" />
</ThemeProvider>
);
}
5. Foydalanuvchi tanlovi
Ko'p ilovalar sozlamalarda "Tizim / Yorug' / Qorong'i" tanlovini beradi:
import { Appearance } from 'react-native';
Appearance.setColorScheme('dark'); // majburan qorong'i
Appearance.setColorScheme('light');
Appearance.setColorScheme(null); // tizimga qaytish
Tanlovni qurilmada saqlash — AsyncStorage (34-dars) va ilova ochilganda qo'llash.
Dizayn maslahatlari
- Sof qora emas —
#000o'rniga to'q ko'k-kulrang (#0b1120). Ko'zga yumshoqroq, soyalar va qatlamlar ko'rinadi - Qorong'ida chuqurlik — yorqinlik bilan: yuqoridagi qatlam (karta) fondan biroz ochroq. Soyalar qorong'ida deyarli ko'rinmaydi
- Asosiy rangni biroz ochroq qiling (
#0284c7→#38bdf8) — to'q fonda kontrast yetarli bo'lsin - Rasmlar va logotiplar — qorong'i fonda ko'rinishini tekshiring (shaffof PNG dagi qora logo yo'qolib qoladi)
- Ikkala rejimda ham kontrastni tekshiring — matn va fon orasida kamida 4.5:1
Nima uchun shunday?
Nima uchun ranglarni "oq/qora" emas, "fon/matn" deb nomlash kerak?
Chunki rang — bu rol, qiymat emas. Agar komponentda color: ranglar.qora yozilgan bo'lsa — qorong'i rejimda u "qora" bo'lib qolishi kerakmi yoki "oq" ga aylanishi kerakmi? Noaniq. color: m.matn esa aniq: "asosiy matn rangi" — yorug'da qora, qorong'ida oq. Rollar bo'yicha nomlash dizayn tizimini rejimdan, brenddan va hatto kelajakdagi "yuqori kontrast" rejimidan mustaqil qiladi.
Xulosa
Eslab qoling:
app.json:"userInterfaceStyle": "automatic"useColorScheme()—'light'/'dark', avtomatik yangilanadi- Ranglar — rol bo'yicha:
fon,matn,karta,chegara,asosiy useMavzu()hook; StyleSheet da tuzilma, massivda ranglar- Navigatsiya —
ThemeProvider+DarkTheme;StatusBar style="auto" Appearance.setColorScheme— foydalanuvchi tanlovi- Sof qora emas; qorong'ida asosiy rangni ochroq qiling
Keyingi dars
18-dars: Safe area — notch, status bar, pastki panel