RN Lezione 6: Flexbox, Card e Layout avanzati
Obiettivi
Section titled “Obiettivi”- Dominare Flexbox per layout professionali
- Creare card, griglie, layout a colonne
- Usare flexWrap per layout responsivi
1. Flexbox — il sistema di layout di RN
Section titled “1. Flexbox — il sistema di layout di RN”In React Native tutti i View hanno display: flex di default.
flex — quanto spazio occupi?
Section titled “flex — quanto spazio occupi?”┌─────────────────────────────┐│ flex: 1 │ ← Occupa 1/3├─────────────────────────────┤│ flex: 2 │ ← Occupa 2/3└─────────────────────────────┘<View style={{ flex: 1, backgroundColor: 'red' }} /><View style={{ flex: 2, backgroundColor: 'blue' }} />// ↑ rosso = 1/3, blu = 2/3 dello spazioRegola:
flex= “quanto spazio prendo rispetto agli altri”
flexDirection — direzione principale
Section titled “flexDirection — direzione principale”flexDirection: 'column' // Verticale (DEFAULT)flexDirection: 'row' // OrizzontaleflexDirection: 'column-reverse'flexDirection: 'row-reverse'// Riga orizzontale<View style={{ flexDirection: 'row' }}> <Text>Uno</Text> <Text>Due</Text> <Text>Tre</Text></View>// Output: UnoDueTre (in orizzontale)justifyContent — allineamento sull’asse principale
Section titled “justifyContent — allineamento sull’asse principale”flex-start (default) [elemento1][elemento2] │center ──────[elemento1][elemento2]────── │flex-end ────────────[elemento1][elemento2] │space-between [elemento1]───────[elemento2] │space-around ──[elemento1]───[elemento2]── │space-evenly ───[elemento1]───[elemento2]─── │alignItems — allineamento sull’asse secondario
Section titled “alignItems — allineamento sull’asse secondario”stretch (default) [───────] ← si stira [───────]
center [───] [───] ← centrato
flex-start [───] ← in alto [───]
flex-end [───] ← in basso [───]2. Pattern: layout a tre colonne
Section titled “2. Pattern: layout a tre colonne”<View style={{ flex: 1, flexDirection: 'row' }}> <View style={{ flex: 1, backgroundColor: 'red' }} /> <View style={{ flex: 2, backgroundColor: 'green' }} /> <View style={{ flex: 1, backgroundColor: 'blue' }} /></View>┌──────┬──────────────────────┬──────┐│ red │ green │ blue ││ 1/4 │ 2/4 │ 1/4 │└──────┴──────────────────────┴──────┘3. Pattern: griglia con flexWrap
Section titled “3. Pattern: griglia con flexWrap”<View style={{ flexDirection: 'row', flexWrap: 'wrap', // ← va a capo justifyContent: 'space-between', padding: 10,}}> <View style={{ width: '48%', height: 100, backgroundColor: 'red' }} /> <View style={{ width: '48%', height: 100, backgroundColor: 'green' }} /> <View style={{ width: '48%', height: 100, backgroundColor: 'blue' }} /> <View style={{ width: '48%', height: 100, backgroundColor: 'orange' }} /></View>┌────────┐ ┌────────┐│ red │ │ green │└────────┘ └────────┘┌────────┐ ┌────────┐│ blue │ │ orange │└────────┘ └────────┘4. Pattern: card prodotto con flexDirection row
Section titled “4. Pattern: card prodotto con flexDirection row”const CardProdotto = ({ nome, prezzo, immagine }) => ( <View style={styles.card}> <Image source={{ uri: immagine }} style={styles.img} /> <View style={styles.info}> <Text style={styles.nome}>{nome}</Text> <Text style={styles.prezzo}>€ {prezzo.toFixed(2)}</Text> <TouchableOpacity style={styles.bottone}> <Text style={styles.bottoneTesto}>Aggiungi</Text> </TouchableOpacity> </View> </View>);
const styles = StyleSheet.create({ card: { flexDirection: 'row', // ← orizzontale backgroundColor: 'white', borderRadius: 12, padding: 10, marginBottom: 10, elevation: 2, }, img: { width: 80, height: 80, borderRadius: 8, marginRight: 12, }, info: { flex: 1, // ← occupa spazio rimanente justifyContent: 'center', }, nome: { fontSize: 16, fontWeight: 'bold', }, prezzo: { fontSize: 18, color: '#2ecc71', fontWeight: 'bold', marginVertical: 5, }, bottone: { backgroundColor: '#3498db', paddingHorizontal: 15, paddingVertical: 8, borderRadius: 8, alignSelf: 'flex-start', // ← non si allarga }, bottoneTesto: { color: 'white', fontWeight: '600', },});5. Pattern: layout di schermata completa
Section titled “5. Pattern: layout di schermata completa”┌────────────────────────┐│ Header │ ← flex: 0 (contenuto)├────────────────────────┤│ ││ Content │ ← flex: 1 (si espande)│ │├────────────────────────┤│ Footer │ ← flex: 0└────────────────────────┘export default function App() { return ( <View style={{ flex: 1 }}> {/* Header */} <View style={styles.header}> <Text style={styles.titolo}>La mia App</Text> </View>
{/* Content (si espande) */} <View style={styles.content}> <Text>Contenuto principale...</Text> </View>
{/* Footer */} <View style={styles.footer}> <Text>© 2026</Text> </View> </View> );}
const styles = StyleSheet.create({ header: { padding: 20, backgroundColor: '#3498db', alignItems: 'center', }, titolo: { fontSize: 22, fontWeight: 'bold', color: 'white', }, content: { flex: 1, // ← occupa TUTTO lo spazio rimanente padding: 20, }, footer: { padding: 15, backgroundColor: '#f0f0f0', alignItems: 'center', },});6. Pattern: posizionamento assoluto
Section titled “6. Pattern: posizionamento assoluto”// Overlay su un'immagine<View style={{ width: 200, height: 200 }}> <Image source={{ uri: '...' }} style={{ width: '100%', height: '100%' }} /> <Text style={{ position: 'absolute', bottom: 10, left: 10, color: 'white', fontSize: 20, fontWeight: 'bold', }}> Titolo foto </Text></View>7. Gap (spazio tra elementi)
Section titled “7. Gap (spazio tra elementi)”// React Native 0.71+<View style={{ flexDirection: 'row', gap: 10 }}> <Item /> <Item /> <Item /></View>
// In alternativa (pre-0.71)<View style={{ flexDirection: 'row' }}> <Item style={{ marginRight: 10 }} /> <Item style={{ marginRight: 10 }} /> <Item /></View>8. Tabella riassuntiva Flexbox
Section titled “8. Tabella riassuntiva Flexbox”| Proprietà | Valori comuni | Descrizione |
|---|---|---|
flex | numero | Quanto spazio occupa |
flexDirection | 'column', 'row' | Asse principale |
justifyContent | 'center', 'space-between', 'flex-start' | Allineamento asse principale |
alignItems | 'center', 'stretch', 'flex-start' | Allineamento asse secondario |
alignSelf | 'center', 'flex-start' | Allineamento individuale |
flexWrap | 'wrap', 'nowrap' | Vai a capo? |
gap | numero | Spazio tra elementi |
position | 'relative', 'absolute' | Posizionamento |
9. Esercizio autonomo
Section titled “9. Esercizio autonomo”🎯 Esercizio: “Griglia menu ristorante”
Section titled “🎯 Esercizio: “Griglia menu ristorante””Crea una schermata che mostri un menu usando una griglia 2×N con flexWrap:
- Ogni card: immagine in alto, nome sotto, prezzo in basso
- Griglia con
flexWrap: 'wrap', larghezza ~48% - Header con nome ristorante
- Categorie come badge colorati sopra ogni piatto
const MENU = [ { id: 1, nome: 'Margherita', prezzo: 6.50, categoria: 'Pizza', img: 'https://picsum.photos/seed/pizza1/200' }, { id: 2, nome: 'Carbonara', prezzo: 8.00, categoria: 'Pasta', img: 'https://picsum.photos/seed/pasta1/200' }, { id: 3, nome: 'Insalata', prezzo: 5.50, categoria: 'Insalate', img: 'https://picsum.photos/seed/insalata1/200' }, { id: 4, nome: 'Tiramisù', prezzo: 4.00, categoria: 'Dolci', img: 'https://picsum.photos/seed/dolce1/200' },];