Kurs React Native · Moduł 2: Listy i style
Responsywność i Dimensions
W tej lekcji3
Aplikacje mobilne muszą działać na różnych rozmiarach ekranów. Poznajmy techniki responsywności!
Dimensions API
import { View, Text, StyleSheet, Dimensions, useWindowDimensions } from 'react-native';
// Statyczne wymiary (przy starcie aplikacji)
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window');
export default function DimensionsExample() {
// Hook - aktualizuje się przy obrocie ekranu
const { width, height } = useWindowDimensions();
const isLandscape = width > height;
const isTablet = width >= 768;
return (
<View style={styles.container}>
<Text style={styles.text}>Szerokość: {width}px</Text>
<Text style={styles.text}>Wysokość: {height}px</Text>
<Text style={styles.text}>
Orientacja: {isLandscape ? 'Pozioma' : 'Pionowa'}
</Text>
<Text style={styles.text}>
Urządzenie: {isTablet ? 'Tablet' : 'Telefon'}
</Text>
{/* Responsywne karty */}
<View style={[
styles.cardContainer,
isLandscape && styles.cardContainerLandscape
]}>
<View style={[styles.card, { width: width * 0.4 }]}>
<Text style={styles.cardText}>Karta 1</Text>
</View>
<View style={[styles.card, { width: width * 0.4 }]}>
<Text style={styles.cardText}>Karta 2</Text>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
backgroundColor: '#1a5276',
},
text: {
fontSize: 16,
color: '#fff',
marginBottom: 8,
},
cardContainer: {
flexDirection: 'column',
gap: 16,
marginTop: 20,
},
cardContainerLandscape: {
flexDirection: 'row',
},
card: {
backgroundColor: '#2c3e50',
padding: 20,
borderRadius: 12,
minWidth: 150,
},
cardText: {
color: '#fff',
textAlign: 'center',
},
});Procentowe wymiary
import { View, StyleSheet } from 'react-native';
export default function PercentageExample() {
return (
<View style={styles.container}>
{/* Procenty działają! */}
<View style={styles.halfWidth} />
<View style={styles.thirdWidth} />
<View style={styles.fullWidth} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
gap: 10,
backgroundColor: '#1a5276',
},
halfWidth: {
width: '50%',
height: 60,
backgroundColor: '#e74c3c',
borderRadius: 8,
},
thirdWidth: {
width: '33.33%',
height: 60,
backgroundColor: '#2ecc71',
borderRadius: 8,
},
fullWidth: {
width: '100%',
height: 60,
backgroundColor: '#3498db',
borderRadius: 8,
},
});Grid responsywny
import { View, Text, StyleSheet, useWindowDimensions } from 'react-native';
export default function ResponsiveGrid() {
const { width } = useWindowDimensions();
// Oblicz liczbę kolumn na podstawie szerokości
const numColumns = width >= 768 ? 4 : width >= 480 ? 3 : 2;
const itemWidth = (width - 40 - (numColumns - 1) * 10) / numColumns;
const items = Array.from({ length: 12 }, (_, i) => i + 1);
return (
<View style={styles.container}>
<Text style={styles.title}>Grid: {numColumns} kolumny</Text>
<View style={styles.grid}>
{items.map((item) => (
<View
key={item}
style={[styles.gridItem, { width: itemWidth, height: itemWidth }]}
>
<Text style={styles.itemText}>{item}</Text>
</View>
))}
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#1a5276',
},
title: {
fontSize: 18,
fontWeight: 'bold',
color: '#fff',
marginBottom: 16,
},
grid: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 10,
},
gridItem: {
backgroundColor: '#2c3e50',
borderRadius: 12,
justifyContent: 'center',
alignItems: 'center',
},
itemText: {
color: '#fff',
fontSize: 20,
fontWeight: 'bold',
},
});Kod do tej lekcji: App.tsx
import React from 'react';
import { View, Text, StyleSheet, useWindowDimensions } from 'react-native';
export default function App() {
const { width } = useWindowDimensions();
// TODO: oblicz liczbę kolumn na podstawie szerokości ekranu.
// Jeśli width >= 768, ustaw numColumns na 4, w przeciwnym razie na 2.
// Przykład: const numColumns = width >= 768 ? 4 : 2;
const numColumns = 2;
const itemWidth = (width - 40 - (numColumns - 1) * 10) / numColumns;
const items = Array.from({ length: 8 }, (_, i) => i + 1);
return (
<View style={styles.container}>
<Text style={styles.title}>Skarby Atlantydy: {numColumns} kolumny</Text>
<View style={styles.grid}>
{items.map((item) => (
<View
key={item}
style={[styles.gridItem, { width: itemWidth, height: itemWidth }]}
>
<Text style={styles.itemText}>{item}</Text>
</View>
))}
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#1a5276',
},
title: {
fontSize: 18,
fontWeight: 'bold',
color: '#fff',
marginBottom: 16,
},
grid: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 10,
},
gridItem: {
backgroundColor: '#2c3e50',
borderRadius: 12,
justifyContent: 'center',
alignItems: 'center',
},
itemText: {
color: '#fff',
fontSize: 20,
fontWeight: 'bold',
},
});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. Jak pobrać szerokość ekranu za pomocą Dimensions API?
2. Czy React Native obsługuje wartości procentowe w stylach?
Zadania praktyczne w grze
- Układanie w poziomie
Ułóż poprawne użycie hooka useWindowDimensions:
- Edytor kodu
Uzupełnij kod responsywnej siatki.