Cámara y galería en React Native
Clase 21 de 22 • Curso de Fundamentos de React Native
Contenido del curso
Módulo 2: Construcción de la Interfaz de Usuario
- 5

Uso de constantes y condicionales en archivos TSX de React Native
10:36 min - 6

Componentes reutilizables en React Native
14:50 min - 7

StyleSheet y Flexbox en React Native
11:24 min - 8

Paleta de colores con hooks en React Native
13:07 min - 9

useState para interfaces dinámicas en React Native
12:12 min - 10

Estado interactivo en React Native con useCallback
13:24 min - 11

Pressable vs TouchableOpacity en React Native
09:37 min
Módulo 3: Interactividad y Manejo de Datos
- 12

Crear un carrusel con ScrollView horizontal
10:51 min - 13

Diferencias entre ScrollView y FlatList para listas grandes
09:47 min - 14

Instalación de Async Storage para persistencia de datos en React Native
14:54 min - 15

Context y Provider para estado global de hábitos
12:08 min - 16

Context y provider para persistir hábitos en React Native
13:19 min - 17

React Native: Provider de animación con confetti
11:58 min - 18

Cómo crear una ExploreCard específica para iOS y Android
09:48 min - 19

Implementación del tab Explore con FlatList y carga asíncrona
12:49 min - 20

Contexto de perfil con persistencia y avatar aleatorio usando IA
12:32 min - 21

Cámara y galería en React Native
Viendo ahora
Módulo 4: Visualización de Listas y Contenido
Integra la cámara y la galería del sistema operativo para crear un perfil completo con avatar, persistencia local y generación con IA. Aquí verás cómo estructurar el componente de avatar, manejar estados con contexto, solicitar permisos y guardar datos de forma segura en el dispositivo. Todo con un flujo claro y práctico.
¿Cómo se integra la librería de cámara y galería del sistema?
Usa una librería que accede a la cámara y a la galería nativas. Se importa como ImagePicker, se configuran opciones como la calidad (por ejemplo, 0.8) y se manejan los casos de cancelación. Además, se validan permisos de cámara y se muestran alertas cuando no han sido otorgados. El ejemplo se apoya en el esquema del sistema operativo, en este caso iOS, sin soluciones externas.
¿Qué opciones y permisos se configuran?
- Importar las funciones de ImagePicker en la parte superior.
- Definir calidad entre 0 y 1: 0.8 recomendado para equilibrio.
- Comprobar si el usuario canceló: no actualizar el estado.
- Solicitar y validar permisos de cámara.
- Mostrar una alerta si no hay permisos.
// importación en la parte superior import * as ImagePicker from 'image-picker'; // elegir desde galería const chooseFromGallery = async () => { const result = await ImagePicker.launchImageLibraryAsync({ // tipo de imagen según librería. quality: 0.8, }); if (result.canceled) return; setAvatar(result.assets?.[0]?.uri); }; // tomar foto con cámara const takePhoto = async () => { const { status } = await ImagePicker.requestCameraPermissionsAsync(); if (status !== 'granted') { alert('otorga permisos de cámara'); return; } const result = await ImagePicker.launchCameraAsync({ quality: 0.8 }); if (result.canceled) return; setAvatar(result.assets?.[0]?.uri); };
¿Cómo elegir desde galería o tomar foto?
- Galería: abrir el selector nativo y actualizar el avatar si no se cancela.
- Cámara: solicitar permisos, lanzar la cámara y guardar el resultado si continúa.
- Fallback: si no hay imagen elegida, mantener el avatar actual.
¿Cómo se construye el componente avatar reutilizable?
Se exporta un componente que recibe tamaño, nombre, url y un onPress. Usa Image con la prop source para la URL, estilos con borderRadius para el círculo perfecto y un util para mostrar iniciales cuando no hay imagen. El botón reutilizable envuelve el contenido para permitir pulsar y abrir la galería o la cámara.
// utils: obtener iniciales del nombre const getInitials = (name = '') => name.trim().split(' ').map(p => p[0]).slice(0, 2).join('').toUpperCase(); export function Avatar({ size = 96, name = '', url, onPress }) { const circle = { width: size, height: size, borderRadius: size / 2 }; return ( <Button onPress={onPress}> <View style={[{ alignItems: 'center', justifyContent: 'center' }, circle]}> {url ? ( <Image source={{ uri: url }} style={circle} /> ) : ( <Text style={{ fontWeight: '700' }}>{getInitials(name)}</Text> )} </View> </Button> ); }
¿Cómo mostrar iniciales si no hay imagen?
- Verificar si la url existe.
- Si no existe: renderizar las iniciales del nombre.
- Mantener accesible el onPress para cambiar el avatar cuando se desee.
¿Cómo gestionar el perfil: estados, guardado y generación con IA?
Se consume un contexto con useProfile y se crean useState para name, role e indicadores de carga. Con useEffect se hace la primera carga del perfil (name y role). El botón de guardar llama al servicio de update desde el contexto, usa textos por defecto cuando faltan campos y muestra una alerta tras guardar. Además, existe una función asíncrona para generar un avatar con IA a partir del nombre como semilla.
// estados locales const [name, setName] = useState(''); const [role, setRole] = useState(''); const [busy, setBusy] = useState(false); const { profile, updateProfile } = useProfile(); const [avatar, setAvatar] = useState(profile?.avatar); // primera carga de datos useEffect(() => { setName(profile?.name); setRole(profile?.role); }, [profile?.name, profile?.role]); // guardar cambios const save = async () => { setBusy(true); await updateProfile({ name: name || 'sin nombre', role: role || 'sin rol', avatar, }); setBusy(false); alert('datos guardados'); }; // generar avatar con IA const generateWithAI = async () => { setBusy(true); const url = await service.generateAvatarWithAI(name); setAvatar(url); setBusy(false); };
¿Cómo se organiza la interfaz del perfil?
- KeyboardAvoidingView: evita que el teclado oculte elementos.
- Platform para ajustar comportamiento en iOS.
- ScrollView: contenido breve sin listas extensas.
- TextInput: controla name y role con useState.
- Botones: tomar foto, elegir de galería, generar con IA y guardar.
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : undefined}> <ScrollView> <View style={{ alignItems: 'center', margin: 16 }}> <Avatar name={name} url={avatar} onPress={chooseFromGallery} /> </View> <View> <Text>nombre</Text> <TextInput value={name} onChangeText={setName} style={styles.input} /> <Text>profesión</Text> <TextInput value={role} onChangeText={setRole} style={styles.input} /> </View> <Button title="tomar foto" onPress={takePhoto} /> <Button title="elegir de galería" onPress={chooseFromGallery} /> <PrimaryButton title="generar con ia" onPress={generateWithAI} /> <PrimaryButton title="guardar" onPress={save} /> </ScrollView> </KeyboardAvoidingView>
// estilos mínimos del input const styles = { input: { borderWidth: 1, borderRadius: 8, padding: 10, marginVertical: 8 }, };
¿Cómo se habilita el acceso global a los datos?
- Agregar el provider del perfil en la raíz de la app.
- Así, todas las pantallas consumen el contexto sin pasar props.
<ProfileProvider> <App /> </ProfileProvider>
- Los datos se almacenan en el dispositivo: permanecen al regresar.
- Puedes sobrescribir el avatar generando otro o eligiendo una nueva imagen.
- La experiencia se mantiene fluida gracias a un loader cuando el perfil está cargando.
¿Te gustaría ver variantes de estilos o flujos de permisos? Deja un comentario con tus dudas o ideas para seguir iterando este perfil con avatar y IA.