Kurs React Native · Moduł 2: Listy i style
StyleSheet - zaawansowane stylowanie
W tej lekcji4
StyleSheet to podstawa stylowania w React Native. Poznajmy zaawansowane techniki!
Tworzenie stylów
import { View, Text, StyleSheet } from 'react-native';
export default function StyleExample() {
return (
<View style={styles.container}>
{/* Pojedynczy styl */}
<Text style={styles.title}>Tytuł</Text>
{/* Łączenie stylów (array) */}
<Text style={[styles.text, styles.bold]}>Pogrubiony tekst</Text>
{/* Style warunkowe */}
<Text style={[styles.text, isActive && styles.active]}>
Warunkowy styl
</Text>
{/* Inline + StyleSheet */}
<Text style={[styles.text, { color: 'red' }]}>
Inline override
</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
},
title: {
fontSize: 24,
fontWeight: 'bold',
},
text: {
fontSize: 16,
},
bold: {
fontWeight: 'bold',
},
active: {
color: '#3498db',
},
});Flexbox w React Native
Flexbox działa podobnie jak w CSS, ale z kilkoma różnicami:
import { View, Text, StyleSheet } from 'react-native';
export default function FlexboxExample() {
return (
<View style={styles.container}>
{/* Flex direction - domyślnie column! */}
<View style={styles.column}>
<View style={styles.box1} />
<View style={styles.box2} />
<View style={styles.box3} />
</View>
{/* Row direction */}
<View style={styles.row}>
<View style={styles.box1} />
<View style={styles.box2} />
<View style={styles.box3} />
</View>
{/* Flex grow */}
<View style={styles.row}>
<View style={[styles.box1, { flex: 1 }]} />
<View style={[styles.box2, { flex: 2 }]} />
<View style={[styles.box3, { flex: 1 }]} />
</View>
{/* Justify & Align */}
<View style={styles.centered}>
<Text style={styles.text}>Wycentrowany</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
gap: 20,
backgroundColor: '#1a5276',
},
column: {
flexDirection: 'column', // Domyślne w RN
gap: 10,
},
row: {
flexDirection: 'row',
gap: 10,
},
centered: {
flex: 1,
justifyContent: 'center', // Oś główna
alignItems: 'center', // Oś poprzeczna
backgroundColor: '#2c3e50',
borderRadius: 12,
},
box1: {
width: 60,
height: 60,
backgroundColor: '#e74c3c',
borderRadius: 8,
},
box2: {
width: 60,
height: 60,
backgroundColor: '#2ecc71',
borderRadius: 8,
},
box3: {
width: 60,
height: 60,
backgroundColor: '#3498db',
borderRadius: 8,
},
text: {
color: '#fff',
fontSize: 18,
},
});Position: absolute
import { View, Text, StyleSheet } from 'react-native';
export default function PositionExample() {
return (
<View style={styles.container}>
<View style={styles.card}>
<Text style={styles.cardTitle}>Karta skarbu</Text>
{/* Badge w prawym górnym rogu */}
<View style={styles.badge}>
<Text style={styles.badgeText}>NOWY</Text>
</View>
{/* Ikona w lewym dolnym rogu */}
<View style={styles.icon}>
<Text>◆</Text>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#1a5276',
},
card: {
width: 250,
height: 150,
backgroundColor: '#2c3e50',
borderRadius: 16,
padding: 20,
// Parent musi mieć position dla absolute children
},
cardTitle: {
fontSize: 20,
fontWeight: 'bold',
color: '#fff',
},
badge: {
position: 'absolute',
top: -10,
right: -10,
backgroundColor: '#e74c3c',
paddingHorizontal: 10,
paddingVertical: 4,
borderRadius: 12,
},
badgeText: {
color: '#fff',
fontSize: 12,
fontWeight: 'bold',
},
icon: {
position: 'absolute',
bottom: 10,
left: 10,
width: 40,
height: 40,
backgroundColor: '#f39c12',
borderRadius: 20,
justifyContent: 'center',
alignItems: 'center',
},
});Cienie (Shadow)
import { View, Text, StyleSheet, Platform } from 'react-native';
export default function ShadowExample() {
return (
<View style={styles.container}>
{/* iOS shadow */}
<View style={styles.cardIOS}>
<Text style={styles.text}>iOS Shadow</Text>
</View>
{/* Android shadow (elevation) */}
<View style={styles.cardAndroid}>
<Text style={styles.text}>Android Elevation</Text>
</View>
{/* Cross-platform shadow */}
<View style={styles.cardCrossplatform}>
<Text style={styles.text}>Cross-platform</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
gap: 30,
backgroundColor: '#ecf0f1',
},
cardIOS: {
width: 200,
padding: 20,
backgroundColor: '#fff',
borderRadius: 12,
// iOS only
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.3,
shadowRadius: 8,
},
cardAndroid: {
width: 200,
padding: 20,
backgroundColor: '#fff',
borderRadius: 12,
// Android only
elevation: 8,
},
cardCrossplatform: {
width: 200,
padding: 20,
backgroundColor: '#fff',
borderRadius: 12,
// Oba platformy
...Platform.select({
ios: {
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.3,
shadowRadius: 8,
},
android: {
elevation: 8,
},
}),
},
text: {
textAlign: 'center',
fontSize: 16,
},
});Kod do tej lekcji: App.tsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<View style={styles.card}>
<Text style={styles.emoji}>{'><>'}</Text>
<Text style={styles.name}>Rybka koralowa</Text>
<Text style={styles.description}>Mieszkanka raf Atlantydy</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#aed6f1',
},
card: {
width: 220,
padding: 20,
backgroundColor: '#fff',
alignItems: 'center',
// TODO: dodaj borderRadius: 16, aby zaokrąglić rogi karty
// TODO: dodaj cień iOS:
// shadowColor: '#000',
// shadowOffset: { width: 0, height: 4 },
// shadowOpacity: 0.25,
// shadowRadius: 8,
// TODO: dodaj cień Android: elevation: 8,
},
emoji: {
fontSize: 48,
marginBottom: 8,
},
name: {
fontSize: 18,
fontWeight: '600',
color: '#2c3e50',
},
description: {
fontSize: 14,
color: '#7f8c8d',
marginTop: 4,
},
});Hasła z dokumentacji w tej lekcji
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Która wartość justifyContent rozmieszcza elementy równomiernie z równymi odstępami między nimi?
2. Co robi position: 'absolute' w React Native?
Zadania praktyczne w grze
- Układanie w pionie
Uporządkuj wartości justifyContent od najmniejszego do największego odstępu na końcach:
- Klikanie w kolejności
Kliknij właściwości cienia w odpowiedniej kolejności (iOS):
- Edytor kodu
Uzupełnij style dla karty z efektem cienia.