12. Componente View
Tutorial: Componente View en React Native
📱 Parte 12: Componente View - El Contenedor Fundamental
🎯 Objetivo:
Aprender a usar el componente View de React Native como contenedor principal, entender su comportamiento y aplicar estilos para crear layouts básicos.
📸 Analizando el Ejemplo de la Imagen
Observando el código de la imagen:
javascript
import React from 'react';
import { View } from 'react-native';
const App = () => {
return (
<View> {/* Contenedor padre */}
<View style={{backgroundColor: 'green', width: 150, height: 150}} />
<View style={{backgroundColor: 'black', width: 150, height: 150}} />
<View style={{backgroundColor: 'gray', width: 150, height: 150}} />
</View>
);
};
export default App;
Resultado visual esperado:
text
┌─────────────────────────────────┐
│ ┌─────────────┐ │
│ │ VERDE │ │
│ │ │ │
│ └─────────────┘ │
│ ┌─────────────┐ │
│ │ NEGRO │ │
│ │ │ │
│ └─────────────┘ │
│ ┌─────────────┐ │
│ │ GRIS │ │
│ │ │ │
│ └─────────────┘ │
└─────────────────────────────────┘
🚀 Paso 1: ¿Qué es el Componente View?
View es el contenedor fundamental en React Native, equivalente a <div> en HTML. Es el bloque de construcción básico para crear interfaces.
1.1 Importación Básica
javascript
import React from 'react';
import { View } from 'react-native'; // ¡IMPORTANTE importar View!
📦 Paso 2: Creando Views Básicos
2.1 View Simple
javascript
const ViewBasico = () => {
return (
<View>
{/* Este View no muestra nada visible */}
</View>
);
};
2.2 View con Estilos (Como en el Ejemplo)
javascript
const ViewConEstilos = () => {
return (
<View style={{
backgroundColor: 'blue',
width: 200,
height: 200,
margin: 20
}}>
{/* Contenido del View */}
</View>
);
};
2.3 DEMOSTRACIÓN: Views Anidados
javascript
const ViewsAnidados = () => {
return (
{/* View contenedor principal */}
<View style={styles.contenedorPrincipal}>
{/* View hijo 1 */}
<View style={styles.viewHijo1}>
<Text>Hijo 1</Text>
</View>
{/* View hijo 2 */}
<View style={styles.viewHijo2}>
{/* View nieto dentro del hijo 2 */}
<View style={styles.viewNieto}>
<Text>Nieto</Text>
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
contenedorPrincipal: {
flex: 1,
backgroundColor: '#f0f0f0',
padding: 20,
},
viewHijo1: {
backgroundColor: 'red',
height: 100,
justifyContent: 'center',
alignItems: 'center',
marginBottom: 10,
},
viewHijo2: {
backgroundColor: 'blue',
height: 200,
padding: 20,
},
viewNieto: {
backgroundColor: 'yellow',
height: 100,
justifyContent: 'center',
alignItems: 'center',
},
});
🎨 Paso 3: Propiedades Clave del Componente View
3.1 Propiedades de Estilo Esenciales
javascript
<View
style={{
// Tamaño
width: 100, // Ancho en puntos
height: 100, // Alto en puntos
minWidth: 50, // Ancho mínimo
minHeight: 50, // Alto mínimo
maxWidth: 200, // Ancho máximo
maxHeight: 200, // Alto máximo
// Colores y fondos
backgroundColor: 'red', // Color de fondo
opacity: 0.8, // Transparencia (0 a 1)
// Bordes
borderWidth: 2, // Grosor del borde
borderColor: 'black', // Color del borde
borderRadius: 10, // Bordes redondeados
borderTopWidth: 5, // Borde superior específico
// Espaciado
margin: 10, // Margen exterior
marginTop: 5, // Margen superior específico
padding: 15, // Relleno interior
paddingLeft: 20, // Relleno izquierdo específico
// Posicionamiento
position: 'relative', // 'relative' o 'absolute'
top: 10, // Desde arriba (absolute)
left: 20, // Desde izquierda (absolute)
zIndex: 1, // Nivel de apilamiento
// Sombra (iOS)
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 3.84,
// Elevación (Android)
elevation: 5,
}}
>
3.2 Ejemplo Completo con Todas las Propiedades
javascript
const ViewCompleto = () => {
return (
<View style={styles.contenedor}>
{/* View con sombra y bordes redondeados */}
<View style={styles.tarjeta}>
<Text style={styles.textoTarjeta}>Tarjeta con estilo</Text>
</View>
{/* View con posición absoluta */}
<View style={styles.badge}>
<Text style={styles.textoBadge}>Nuevo!</Text>
</View>
{/* View transparente */}
<View style={styles.overlay}>
<Text>Contenido semitransparente</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
contenedor: {
flex: 1,
backgroundColor: '#f5f5f5',
padding: 20,
},
tarjeta: {
width: 200,
height: 150,
backgroundColor: 'white',
borderRadius: 15,
padding: 20,
justifyContent: 'center',
alignItems: 'center',
// Sombra para iOS
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
// Elevación para Android
elevation: 5,
// Borde
borderWidth: 1,
borderColor: '#e0e0e0',
},
badge: {
position: 'absolute',
top: 40,
right: 40,
backgroundColor: 'red',
paddingHorizontal: 10,
paddingVertical: 5,
borderRadius: 12,
},
overlay: {
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
padding: 20,
},
textoTarjeta: {
fontSize: 18,
fontWeight: 'bold',
},
textoBadge: {
color: 'white',
fontWeight: 'bold',
},
});
🔄 Paso 4: Views Anidados - Jerarquía y Estructura
4.1 Ejemplo Práctico: Tarjeta de Producto
javascript
const ProductCard = () => {
return (
{/* View principal de la tarjeta */}
<View style={styles.productCard}>
{/* View para la imagen del producto */}
<View style={styles.imageContainer}>
<View style={styles.imagePlaceholder} />
{/* Aquí iría un componente Image */}
</View>
{/* View para la información del producto */}
<View style={styles.infoContainer}>
{/* View para el título y precio */}
<View style={styles.titleRow}>
<Text style={styles.productTitle}>Producto Ejemplo</Text>
<Text style={styles.productPrice}>$29.99</Text>
</View>
{/* View para la descripción */}
<View style={styles.descriptionContainer}>
<Text>Descripción del producto...</Text>
</View>
{/* View para los botones */}
<View style={styles.buttonsContainer}>
<View style={styles.button}>
<Text style={styles.buttonText}>Comprar</Text>
</View>
<View style={[styles.button, styles.secondaryButton]}>
<Text style={styles.buttonText}>Guardar</Text>
</View>
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
productCard: {
backgroundColor: 'white',
borderRadius: 10,
margin: 10,
padding: 15,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
imageContainer: {
height: 150,
backgroundColor: '#f0f0f0',
borderRadius: 8,
marginBottom: 15,
justifyContent: 'center',
alignItems: 'center',
},
imagePlaceholder: {
width: 100,
height: 100,
backgroundColor: '#ccc',
},
infoContainer: {
// El contenido se organiza automáticamente
},
titleRow: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 10,
},
productTitle: {
fontSize: 18,
fontWeight: 'bold',
flex: 1,
},
productPrice: {
fontSize: 20,
fontWeight: 'bold',
color: '#2e7d32',
},
descriptionContainer: {
marginBottom: 15,
},
buttonsContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
},
button: {
backgroundColor: '#2196f3',
paddingVertical: 10,
paddingHorizontal: 20,
borderRadius: 5,
flex: 1,
marginHorizontal: 5,
alignItems: 'center',
},
secondaryButton: {
backgroundColor: '#f5f5f5',
},
buttonText: {
color: 'white',
fontWeight: 'bold',
},
});
🎯 Paso 5: Flexbox con Views (Diseño Responsivo)
5.1 Conceptos Básicos de Flexbox en View
javascript
const FlexboxBasico = () => {
return (
<View style={styles.flexContainer}>
{/* View con flex: 1 ocupa espacio disponible */}
<View style={[styles.box, { backgroundColor: 'red', flex: 1 }]}>
<Text>Flex: 1</Text>
</View>
{/* View con flex: 2 ocupa el doble que el anterior */}
<View style={[styles.box, { backgroundColor: 'blue', flex: 2 }]}>
<Text>Flex: 2</Text>
</View>
{/* View con flex: 1 ocupa igual que el primero */}
<View style={[styles.box, { backgroundColor: 'green', flex: 1 }]}>
<Text>Flex: 1</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
flexContainer: {
flex: 1,
flexDirection: 'row', // 'row' | 'column'
justifyContent: 'space-between', // Alineación principal
alignItems: 'center', // Alineación secundaria
},
box: {
justifyContent: 'center',
alignItems: 'center',
},
});
5.2 Ejercicio: Layout de Columnas
javascript
const ColumnLayout = () => {
return (
<View style={styles.container}>
{/* Header */}
<View style={styles.header}>
<Text style={styles.headerText}>Mi Aplicación</Text>
</View>
{/* Contenido principal en fila */}
<View style={styles.mainContent}>
{/* Sidebar */}
<View style={styles.sidebar}>
<Text>Menú 1</Text>
<Text>Menú 2</Text>
<Text>Menú 3</Text>
</View>
{/* Contenido */}
<View style={styles.content}>
<Text>Contenido principal aquí</Text>
</View>
{/* Sidebar derecha */}
<View style={styles.sidebar}>
<Text>Widget 1</Text>
<Text>Widget 2</Text>
</View>
</View>
{/* Footer */}
<View style={styles.footer}>
<Text>© 2024 Mi App</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
height: 60,
backgroundColor: '#6200ee',
justifyContent: 'center',
alignItems: 'center',
},
headerText: {
color: 'white',
fontSize: 20,
fontWeight: 'bold',
},
mainContent: {
flex: 1,
flexDirection: 'row',
},
sidebar: {
width: 100,
backgroundColor: '#f5f5f5',
padding: 10,
},
content: {
flex: 1,
backgroundColor: 'white',
padding: 20,
},
footer: {
height: 50,
backgroundColor: '#333',
justifyContent: 'center',
alignItems: 'center',
},
});
⚡ Paso 6: Eventos y Gestos en View
6.1 View como Botón (Pressable)
javascript
const PressableView = () => {
const [pressed, setPressed] = useState(false);
return (
<View
style={[
styles.buttonView,
pressed && styles.buttonPressed
]}
onTouchStart={() => setPressed(true)}
onTouchEnd={() => {
setPressed(false);
console.log('View presionado!');
}}
onLongPress={() => alert('Presión larga!')}
>
<Text>Presióname</Text>
</View>
);
};
const styles = StyleSheet.create({
buttonView: {
width: 200,
height: 50,
backgroundColor: '#007AFF',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 8,
},
buttonPressed: {
backgroundColor: '#0056CC',
transform: [{ scale: 0.95 }],
},
});
6.2 View con Múltiples Eventos
javascript
const InteractiveView = () => {
const [touchCount, setTouchCount] = useState(0);
return (
<View
style={styles.interactiveBox}
onTouchStart={() => console.log('Touch started')}
onTouchMove={(event) => {
const { locationX, locationY } = event.nativeEvent;
console.log(`Moviendo en: ${locationX}, ${locationY}`);
}}
onTouchEnd={() => {
setTouchCount(prev => prev + 1);
console.log('Touch ended');
}}
>
<Text>Toques: {touchCount}</Text>
<Text>¡Tócame!</Text>
</View>
);
};
🛠️ Paso 7: Ejercicio Práctico - Creando un Layout Completo
Objetivo: Crear una pantalla de perfil usando solo Views
javascript
const ProfileScreen = () => {
return (
<View style={styles.container}>
{/* Header */}
<View style={styles.header}>
<View style={styles.avatarContainer}>
<View style={styles.avatar} />
</View>
<View style={styles.userInfo}>
<Text style={styles.userName}>Juan Pérez</Text>
<Text style={styles.userTitle}>Desarrollador React Native</Text>
</View>
</View>
{/* Stats */}
<View style={styles.statsContainer}>
<View style={styles.statItem}>
<Text style={styles.statNumber}>156</Text>
<Text style={styles.statLabel}>Publicaciones</Text>
</View>
<View style={styles.statDivider} />
<View style={styles.statItem}>
<Text style={styles.statNumber}>2.4K</Text>
<Text style={styles.statLabel}>Seguidores</Text>
</View>
<View style={styles.statDivider} />
<View style={styles.statItem}>
<Text style={styles.statNumber}>348</Text>
<Text style={styles.statLabel}>Siguiendo</Text>
</View>
</View>
{/* Bio */}
<View style={styles.bioContainer}>
<Text>Apasionado por el desarrollo móvil y la tecnología.</Text>
</View>
{/* Action Buttons */}
<View style={styles.actionsContainer}>
<View style={styles.primaryButton}>
<Text style={styles.primaryButtonText}>Seguir</Text>
</View>
<View style={styles.secondaryButton}>
<Text style={styles.secondaryButtonText}>Mensaje</Text>
</View>
</View>
{/* Posts Grid */}
<View style={styles.postsGrid}>
{[1, 2, 3, 4, 5, 6].map((item) => (
<View key={item} style={styles.postItem} />
))}
</View>
</View>
);
};
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#fff' },
header: {
flexDirection: 'row',
padding: 20,
alignItems: 'center'
},
avatarContainer: {
marginRight: 15
},
avatar: {
width: 80,
height: 80,
borderRadius: 40,
backgroundColor: '#ccc'
},
userInfo: {
flex: 1
},
userName: {
fontSize: 22,
fontWeight: 'bold'
},
userTitle: {
fontSize: 16,
color: '#666'
},
statsContainer: {
flexDirection: 'row',
paddingVertical: 20,
borderTopWidth: 1,
borderBottomWidth: 1,
borderColor: '#eee'
},
statItem: {
flex: 1,
alignItems: 'center'
},
statNumber: {
fontSize: 20,
fontWeight: 'bold'
},
statLabel: {
fontSize: 14,
color: '#666'
},
statDivider: {
width: 1,
backgroundColor: '#eee'
},
bioContainer: {
padding: 20
},
actionsContainer: {
flexDirection: 'row',
paddingHorizontal: 20,
marginBottom: 20
},
primaryButton: {
flex: 2,
backgroundColor: '#3897f0',
padding: 12,
borderRadius: 5,
alignItems: 'center',
marginRight: 10
},
primaryButtonText: {
color: 'white',
fontWeight: 'bold'
},
secondaryButton: {
flex: 1,
backgroundColor: '#f0f0f0',
padding: 12,
borderRadius: 5,
alignItems: 'center'
},
secondaryButtonText: {
fontWeight: 'bold'
},
postsGrid: {
flexDirection: 'row',
flexWrap: 'wrap',
padding: 2
},
postItem: {
width: '33.33%',
aspectRatio: 1,
backgroundColor: '#f0f0f0',
borderWidth: 1,
borderColor: '#fff'
},
});
📋 Paso 8: Mejores Prácticas con View
8.1 Consejos para un Código Limpio
Evita Views innecesarios - No anides más de lo necesario
Usa StyleSheet.create() en lugar de estilos inline
Nombra tus estilos descriptivamente
Reutiliza componentes en lugar de copiar Views
Mantén la jerarquía plana cuando sea posible
8.2 Ejemplo: Buenas vs Malas Prácticas
javascript
// ❌ MAL: Anidamiento excesivo y estilos inline
const MalEjemplo = () => (
<View>
<View>
<View style={{backgroundColor: 'red', width: 100, height: 100}}>
<Text>Hola</Text>
</View>
</View>
</View>
);
// ✅ BIEN: Estructura plana y estilos separados
const BuenEjemplo = () => (
<View style={styles.container}>
<View style={styles.box}>
<Text style={styles.text}>Hola</Text>
</View>
</View>
);
const styles = StyleSheet.create({
container: { /* estilos */ },
box: {
backgroundColor: 'red',
width: 100,
height: 100,
justifyContent: 'center',
alignItems: 'center'
},
text: { color: 'white' },
});
⚠️ Paso 9: Errores Comunes
❌ Error: "View no se muestra"
javascript
// MAL: Falta tamaño o color
<View>
<Text>Contenido</Text>
</View>
// SOLUCIÓN: Agregar estilos visibles
<View style={{ backgroundColor: '#f0f0f0', padding: 20 }}>
<Text>Contenido</Text>
</View>
❌ Error: "Views se solapan"
javascript
// SOLUCIÓN: Usar flexbox o dimensiones explícitas
<View style={{ flex: 1, flexDirection: 'row' }}>
<View style={{ flex: 1, backgroundColor: 'red' }} />
<View style={{ flex: 1, backgroundColor: 'blue' }} />
</View>
🎯 Resumen: ¿Cuándo usar View?
🎬 Próximo Tutorial
En el siguiente video aprenderemos:
Componente Text para mostrar contenido escrito
Estilización de texto con diferentes fuentes y tamaños
Texto enriquecido con múltiples estilos
Manipulación de texto en React Native
✅ ¡Ahora dominas el componente View! Es el bloque fundamental de todas las aplicaciones React Native. Recuerda: practica creando diferentes layouts y experimenta con las propiedades para entender completamente su poder
Comentarios
Publicar un comentario