RN Lezione 5: Core Components e StyleSheet
Obiettivi
Section titled “Obiettivi”- Conoscere View, Text, Image, ScrollView
- Usare StyleSheet per stili separati
- Gestire ombre, bordi, padding
- Costruire schermate scrollabili
1. I componenti core di React Native
Section titled “1. I componenti core di React Native”| Componente | Equivalente Web | Uso |
|---|---|---|
View | <div> | Contenitore generico |
Text | <p> / <span> | Testo |
TextInput | <input> | Campo input |
Image | <img> | Immagine |
ScrollView | overflow:scroll | Contenitore scrollabile |
Button | <button> | Pulsante semplice |
View — il contenitore universale
Section titled “View — il contenitore universale”View è il mattone fondamentale. Supporta flexbox, stili, eventi.
import { View } from 'react-native';
<View style={{ width: 100, height: 100, backgroundColor: 'blue', borderRadius: 10,}} />Text — il testo
Section titled “Text — il testo”Tutto il testo DEVE stare dentro <Text>.
// ✅ Corretto<Text style={{ fontSize: 18 }}>Ciao mondo</Text>
// ❌ SBAGLIATO — testo fuori da Text<View>Ciao mondo</View>
// Testo annidato (stili ereditati)<Text style={{ color: 'blue' }}> Questo è blu <Text style={{ fontWeight: 'bold' }}> e questo è grassetto</Text></Text>2. StyleSheet — gli stili separati dal markup
Section titled “2. StyleSheet — gli stili separati dal markup”StyleSheet.create() separa il markup dagli stili (come CSS).
import { StyleSheet, View, Text } from 'react-native';
// --- Markup (JSX) ---<View style={styles.container}> <Text style={styles.titolo}>Titolo</Text> <Text style={styles.testo}>Contenuto</Text></View>
// --- Stili (fuori dal componente) ---const styles = StyleSheet.create({ container: { flex: 1, padding: 20, backgroundColor: '#f5f5f5', }, titolo: { fontSize: 24, fontWeight: 'bold', color: '#333', marginBottom: 10, }, testo: { fontSize: 16, color: 'grey', lineHeight: 24, },});Perché StyleSheet e non oggetti inline?
Section titled “Perché StyleSheet e non oggetti inline?”| Oggetto inline | StyleSheet.create() |
|---|---|
<View style={{ padding: 10 }}> | <View style={styles.container}> |
| Ricreato a ogni render | Una volta sola |
| Performance leggermente peggiore | Ottimizzato |
| Difficile da riutilizzare | Facile da riutilizzare |
StyleSheet.compose e array di stili
Section titled “StyleSheet.compose e array di stili”<View style={styles.base} /><View style={[styles.base, styles.extra]} /> // Unisce stili<View style={[styles.base, cond && styles.cond]} /> // Condizionale3. Proprietà stile comuni
Section titled “3. Proprietà stile comuni”Box model
Section titled “Box model”padding: 20, // Tutti i latipaddingHorizontal: 20, // Sinistra + destrapaddingVertical: 10, // Sopra + sottopaddingTop: 10, // Solo sopramargin: 20,marginBottom: 10,Bordo e angoli
Section titled “Bordo e angoli”borderWidth: 2,borderColor: '#ccc',borderRadius: 12, // Angoli arrotondati// Solo alcuni angoli:borderTopLeftRadius: 12,borderBottomRightRadius: 12,Ombre (iOS e Android)
Section titled “Ombre (iOS e Android)”// iOSshadowColor: '#000',shadowOffset: { width: 0, height: 2 },shadowOpacity: 0.1,shadowRadius: 8,
// Androidelevation: 4,fontSize: 18,fontWeight: 'bold', // 'normal' | 'bold' | '100'-'900'fontStyle: 'italic', // 'normal' | 'italic'color: '#333',textAlign: 'center', // 'left' | 'center' | 'right'lineHeight: 24, // Altezza rigaletterSpacing: 1, // Spaziatura tra letteretextTransform: 'uppercase', // 'uppercase' | 'lowercase' | 'capitalize'4. Image
Section titled “4. Image”import { Image } from 'react-native';
// Immagine da web<Image source={{ uri: 'https://picsum.photos/200' }} style={{ width: 200, height: 200, borderRadius: 100 }}/>
// Immagine locale<Image source={require('./assets/logo.png')} style={{ width: 100, height: 100 }}/>
// Con resizeMode<Image source={{ uri: 'https://picsum.photos/300/400' }} style={{ width: '100%', height: 200 }} resizeMode="cover" // ↑ 'cover' (default, ritaglia), 'contain' (adatta), 'stretch'/>5. ScrollView
Section titled “5. ScrollView”ScrollView permette lo scroll quando il contenuto è più grande dello schermo.
import { ScrollView } from 'react-native';
// Scroll verticale (default)<ScrollView style={styles.container}> <Text>Contenuto lungo...</Text> {/* ... */} <Text>Fine contenuto</Text></ScrollView>
// Scroll orizzontale<ScrollView horizontal showsHorizontalScrollIndicator={false}> <View style={{ width: 200, height: 100, backgroundColor: 'red' }} /> <View style={{ width: 200, height: 100, backgroundColor: 'green' }} /> <View style={{ width: 200, height: 100, backgroundColor: 'blue' }} /></ScrollView>Proprietà ScrollView
Section titled “Proprietà ScrollView”| Proprietà | Descrizione |
|---|---|
horizontal | Scroll orizzontale (default: verticale) |
showsVerticalScrollIndicator | Mostra barra scroll verticale |
showsHorizontalScrollIndicator | Mostra barra scroll orizzontale |
contentContainerStyle | Stili per il contenitore interno |
pagingEnabled | Scroll a pagina intera (come iOS springboard) |
6. Esempio guidato: Pagina profilo scrollabile
Section titled “6. Esempio guidato: Pagina profilo scrollabile”import { View, Text, Image, ScrollView, StyleSheet } from 'react-native';
export default function App() { return ( <ScrollView style={styles.container}> {/* Header con foto copertina */} <View style={styles.header}> <Image source={{ uri: 'https://picsum.photos/seed/copertina/400/200' }} style={styles.copertina} /> <Image source={{ uri: 'https://i.pravatar.cc/150?u=mario' }} style={styles.avatar} /> </View>
{/* Info profilo */} <View style={styles.section}> <Text style={styles.nome}>Mario Rossi</Text> <Text style={styles.ruolo}>💻 Sviluppatore mobile</Text> <Text style={styles.bio}> Studente di Informatica, appassionato di React Native e sviluppo mobile. Amo creare app che funzionano su Android e iOS. </Text> </View>
{/* Statistiche */} <View style={styles.statsRow}> <View style={styles.stat}> <Text style={styles.statNumero}>42</Text> <Text style={styles.statLabel}>Progetti</Text> </View> <View style={styles.stat}> <Text style={styles.statNumero}>15</Text> <Text style={styles.statLabel}>App pubblicate</Text> </View> <View style={styles.stat}> <Text style={styles.statNumero}>3</Text> <Text style={styles.statLabel}>Linguaggi</Text> </View> </View>
{/* Competenze */} <View style={styles.section}> <Text style={styles.sectionTitle}>⚡ Competenze</Text> {['React Native', 'Python', 'JavaScript', 'Flet', 'Git'].map((skill, i) => ( <View key={i} style={styles.skillRow}> <Text style={styles.skillNome}>{skill}</Text> <View style={styles.skillBar}> <View style={[styles.skillFill, { width: `${(5 - i) * 25}%` }]} /> </View> </View> ))} </View> </ScrollView> );}
const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f0f4f8', }, header: { alignItems: 'center', marginBottom: 20, }, copertina: { width: '100%', height: 150, }, avatar: { width: 100, height: 100, borderRadius: 50, marginTop: -50, borderWidth: 4, borderColor: 'white', }, section: { backgroundColor: 'white', marginHorizontal: 15, marginBottom: 15, padding: 20, borderRadius: 15, elevation: 2, shadowColor: '#000', shadowOpacity: 0.05, shadowRadius: 5, }, nome: { fontSize: 22, fontWeight: 'bold', textAlign: 'center', }, ruolo: { fontSize: 14, color: 'grey', textAlign: 'center', marginBottom: 10, }, bio: { fontSize: 14, color: '#555', lineHeight: 22, textAlign: 'center', }, statsRow: { flexDirection: 'row', justifyContent: 'space-around', backgroundColor: 'white', marginHorizontal: 15, marginBottom: 15, padding: 15, borderRadius: 15, elevation: 2, }, stat: { alignItems: 'center', }, statNumero: { fontSize: 24, fontWeight: 'bold', color: '#3498db', }, statLabel: { fontSize: 12, color: 'grey', }, sectionTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 15, }, skillRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 10, }, skillNome: { width: 100, fontSize: 14, color: '#555', }, skillBar: { flex: 1, height: 8, backgroundColor: '#e0e0e0', borderRadius: 4, overflow: 'hidden', }, skillFill: { height: '100%', backgroundColor: '#3498db', borderRadius: 4, },});7. Esempi rapidi di pattern comuni
Section titled “7. Esempi rapidi di pattern comuni”Card prodotto
Section titled “Card prodotto”<View style={styles.card}> <Image source={{ uri: 'https://picsum.photos/seed/1/300/200' }} style={styles.cardImg} /> <View style={styles.cardBody}> <Text style={styles.cardTitolo}>Prodotto</Text> <Text style={styles.cardPrezzo}>€ 12.99</Text> </View></View>Separatore
Section titled “Separatore”<View style={{ height: 1, backgroundColor: '#eee', marginVertical: 15 }} /><View style={styles.badge}> <Text style={styles.badgeTesto}>Nuovo</Text></View>8. Tabella riassuntiva
Section titled “8. Tabella riassuntiva”| Componente | Codice minimo |
|---|---|
| View | <View style={...} /> |
| Text | <Text style={...}>testo</Text> |
| Image | <Image source={{uri: '...'}} style={...} /> |
| ScrollView | <ScrollView>...</ScrollView> |
| StyleSheet | const s = StyleSheet.create({...}) |
9. Esercizio autonomo
Section titled “9. Esercizio autonomo”🎯 Esercizio: “Galleria prodotti scrollabile”
Section titled “🎯 Esercizio: “Galleria prodotti scrollabile””Crea una schermata scrollabile con:
- Header con titolo e sfondo colorato
- Almeno 4 card prodotto, ognuna con:
- Immagine (
https://picsum.photos/seed/PRODOTTO/300/200) - Nome prodotto (grassetto, 18px)
- Prezzo (verde, 16px)
- Descrizione (grigio, 14px)
- Immagine (
- Card con angoli arrotondati, ombra, margine
ScrollViewper scrollare tutto
const PRODOTTI = [ { id: 1, nome: 'Pizza Margherita', prezzo: 6.50, desc: 'Pomodoro, mozzarella, basilico' }, { id: 2, nome: 'Pasta Carbonara', prezzo: 8.00, desc: 'Uova, guanciale, pecorino' }, { id: 3, nome: 'Insalata Greca', prezzo: 5.50, desc: 'Feta, olive, cetrioli' }, { id: 4, nome: 'Tiramisù', prezzo: 4.00, desc: 'Mascarpone, caffè, cacao' },];