15. Componente Image

 

Tutorial: Componente Image en React Native

📱 Parte 15: Componente Image - Mostrando Imágenes en tu App

🎯 Objetivo:

Aprender a usar el componente Image para mostrar imágenes en React Native desde diferentes fuentes: archivos locales, URLs remotas y base64.


📸 Analizando el Ejemplo de la Imagen

Observando el código de la imagen:

javascript

<Text style={{margin: 5, fontSize: 20, fontWeight: 'bold', color: 'gray'}}>

  Componente Imagen

</Text>


{/* Imagen local */}

<Image

  style={{width: 150, height: 150}}

  source={require('./imgs/react-native.jpg')}

/>


{/* Imagen remota */}

<Image

  style={{width: 150, height: 150}}

  source={{uri: 'https://reactnative.dev/img/tiny_logo.png'}}

/>

Resultado visual esperado:

text

┌─────────────────────────────────┐

│ Componente Imagen               │

│                                 │

│   ┌─────────────┐               │

│   │             │ ← Imagen local│

│   │  IMAGEN 1   │   (react-native.jpg)│

│   │             │               │

│   └─────────────┘               │

│                                 │

│   ┌─────────────┐               │

│   │             │ ← Imagen URL  │

│   │  IMAGEN 2   │   (tiny_logo.png)│

│   │             │               │

│   └─────────────┘               │

└─────────────────────────────────┘


🚀 Paso 1: ¿Qué es el Componente Image?

Image es el componente para mostrar imágenes en React Native. Es equivalente a <img> en HTML.

1.1 Importación Básica

javascript

import React from 'react';

import { Image } from 'react-native'; // ¡IMPORTANTE importar!


📁 Paso 2: Tres Formas de Cargar Imágenes

2.1 DEMOSTRACIÓN: Las Tres Formas en Acción

javascript

const TresFormasImagen = () => {

  return (

    <View style={styles.container}>

      <Text style={styles.titulo}>3 Formas de Cargar Imágenes</Text>

      

      {/* 1. Imagen Local */}

      <View style={styles.tipoContainer}>

        <Text style={styles.subtitulo}>1. Imagen Local (require)</Text>

        <Image

          style={styles.imagen}

          source={require('./assets/imagen-local.jpg')}

        />

      </View>

      

      {/* 2. Imagen por URL */}

      <View style={styles.tipoContainer}>

        <Text style={styles.subtitulo}>2. Imagen por URL (uri)</Text>

        <Image

          style={styles.imagen}

          source={{

            uri: 'https://reactnative.dev/img/tiny_logo.png'

          }}

        />

      </View>

      

      {/* 3. Imagen Base64 */}

      <View style={styles.tipoContainer}>

        <Text style={styles.subtitulo}>3. Imagen Base64</Text>

        <Image

          style={styles.imagen}

          source={{

            uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='

          }}

        />

      </View>

    </View>

  );

};


const styles = StyleSheet.create({

  container: {

    flex: 1,

    padding: 20,

    backgroundColor: '#fff',

  },

  titulo: {

    fontSize: 24,

    fontWeight: 'bold',

    textAlign: 'center',

    marginBottom: 30,

    color: '#333',

  },

  tipoContainer: {

    marginBottom: 30,

    alignItems: 'center',

  },

  subtitulo: {

    fontSize: 18,

    fontWeight: '600',

    marginBottom: 10,

    color: '#666',

  },

  imagen: {

    width: 150,

    height: 150,

    borderRadius: 10,

  },

});


🖼️ Paso 3: Imágenes Locales (require)

3.1 Cargando desde Archivos Locales

javascript

const ImagenesLocales = () => {

  return (

    <View style={styles.container}>

      <Text style={styles.titulo}>Imágenes Locales</Text>

      

      {/* Ejemplo 1: Imagen en misma carpeta */}

      <Text style={styles.subtitulo}>Misma carpeta:</Text>

      <Image

        style={styles.imagenEjemplo}

        source={require('./mi-imagen.jpg')}

      />

      

      {/* Ejemplo 2: Imagen en subcarpeta */}

      <Text style={styles.subtitulo}>Subcarpeta assets:</Text>

      <Image

        style={styles.imagenEjemplo}

        source={require('./assets/imagenes/logo.png')}

      />

      

      {/* Ejemplo 3: Imágenes dinámicas (requiere construcción especial) */}

      <Text style={styles.subtitulo}>Números consecutivos:</Text>

      <View style={styles.fila}>

        {[1, 2, 3].map(num => (

          <Image

            key={num}

            style={styles.imagenPequena}

            source={require(`./assets/iconos/icono${num}.png`)}

          />

        ))}

      </View>

      

      {/* Consejos */}

      <View style={styles.consejos}>

        <Text style={styles.consejoTitulo}>Consejos para imágenes locales:</Text>

        <Text>• Usa nombres descriptivos</Text>

        <Text>• Organiza en carpetas (assets/images/)</Text>

        <Text>• Optimiza tamaño antes de incluir</Text>

        <Text>• Considera diferentes densidades (@2x, @3x)</Text>

      </View>

    </View>

  );

};

3.2 Importación Condicional (Plataformas)

javascript

const ImagenPlataforma = () => {

  return (

    <Image

      style={styles.imagen}

      source={Platform.select({

        ios: require('./assets/icono-ios.png'),

        android: require('./assets/icono-android.png'),

        default: require('./assets/icono-default.png'),

      })}

    />

  );

};


🌐 Paso 4: Imágenes por URL (Remotas)

4.1 Cargando desde Internet

javascript

const ImagenesRemotas = () => {

  const [cargando, setCargando] = useState(true);

  const [error, setError] = useState(false);

  

  return (

    <View style={styles.container}>

      <Text style={styles.titulo}>Imágenes desde URLs</Text>

      

      {/* URL simple */}

      <Text style={styles.subtitulo}>URL básica:</Text>

      <Image

        style={styles.imagenEjemplo}

        source={{

          uri: 'https://reactnative.dev/img/tiny_logo.png'

        }}

        resizeMode="contain"

      />

      

      {/* URL con headers (si es necesario) */}

      <Text style={styles.subtitulo}>URL con autenticación:</Text>

      <Image

        style={styles.imagenEjemplo}

        source={{

          uri: 'https://api.ejemplo.com/imagen.jpg',

          headers: {

            Authorization: 'Bearer token123',

          },

        }}

      />

      

      {/* Imagen con estados de carga */}

      <Text style={styles.subtitulo}>Con estados de carga:</Text>

      <View style={styles.contenedorCarga}>

        {cargando && (

          <View style={styles.indicadorCarga}>

            <ActivityIndicator size="large" color="#007AFF" />

            <Text>Cargando imagen...</Text>

          </View>

        )}

        

        {error && (

          <View style={styles.errorContainer}>

            <Text style={styles.errorText}>Error al cargar</Text>

          </View>

        )}

        

        <Image

          style={[styles.imagenEjemplo, cargando && styles.imagenOculta]}

          source={{

            uri: 'https://picsum.photos/300/300'

          }}

          onLoadStart={() => setCargando(true)}

          onLoadEnd={() => setCargando(false)}

          onError={() => {

            setCargando(false);

            setError(true);

          }}

        />

      </View>

      

      {/* Ejemplo: Galería de imágenes */}

      <Text style={styles.subtitulo}>Galería de imágenes:</Text>

      <ScrollView horizontal showsHorizontalScrollIndicator={false}>

        {[

          'https://picsum.photos/200/300',

          'https://picsum.photos/200/301',

          'https://picsum.photos/200/302',

          'https://picsum.photos/200/303',

          'https://picsum.photos/200/304',

        ].map((url, index) => (

          <Image

            key={index}

            style={styles.imagenGaleria}

            source={{ uri: url }}

          />

        ))}

      </ScrollView>

    </View>

  );

};

4.2 Propiedades para Imágenes Remotas

javascript

<Image

  source={{

    uri: 'https://ejemplo.com/imagen.jpg',

    method: 'GET',                     // Método HTTP

    headers: {                         // Headers personalizados

      Authorization: 'Bearer token',

      'Custom-Header': 'valor',

    },

    body: JSON.stringify({             // Body para POST

      key: 'value'

    }),

    cache: 'default',                  // 'default', 'reload', 'force-cache', 'only-if-cached'

  }}

/>


🔢 Paso 5: Imágenes Base64

5.1 Usando Base64 Inline

javascript

const ImagenesBase64 = () => {

  // Ejemplo de imagen base64 simple (pixel rojo 1x1)

  const pixelRojo = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';

  

  // Ejemplo más complejo (patrón de ejemplo)

  const patronBase64 = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iIzAwN0FGQiIvPgo8L3N2Zz4=';

  

  return (

    <View style={styles.container}>

      <Text style={styles.titulo}>Imágenes Base64</Text>

      

      {/* Pixel simple */}

      <Text style={styles.subtitulo}>Pixel 1x1:</Text>

      <Image

        style={[styles.imagenEjemplo, { backgroundColor: 'transparent' }]}

        source={{ uri: pixelRojo }}

      />

      

      {/* SVG en base64 */}

      <Text style={styles.subtitulo}>SVG como base64:</Text>

      <Image

        style={styles.imagenEjemplo}

        source={{ uri: patronBase64 }}

      />

      

      {/* Generador dinámico de imágenes */}

      <Text style={styles.subtitulo}>Generador dinámico:</Text>

      <View style={styles.fila}>

        {['#FF6B6B', '#4ECDC4', '#FFE66D', '#6B48FF'].map(color => {

          // Generar imagen base64 dinámica

          const svgBase64 = btoa(`

            <svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">

              <rect width="100" height="100" fill="${color}"/>

              <circle cx="50" cy="50" r="30" fill="white" opacity="0.7"/>

            </svg>

          `);

          

          return (

            <Image

              key={color}

              style={styles.imagenBase64}

              source={{ 

                uri: `data:image/svg+xml;base64,${svgBase64}`

              }}

            />

          );

        })}

      </View>

      

      {/* Consejos Base64 */}

      <View style={styles.consejos}>

        <Text style={styles.consejoTitulo}>¿Cuándo usar Base64?</Text>

        <Text>✅ Imágenes muy pequeñas (íconos)</Text>

        <Text>✅ Cuando no hay acceso a red</Text>

        <Text>✅ Para imágenes dinámicas simples</Text>

        <Text>NO para imágenes grandes (aumenta bundle)</Text>

      </View>

    </View>

  );

};


🎨 Paso 6: Propiedades y Estilos de Image

6.1 Propiedades Principales

javascript

<Image

  // FUENTE DE LA IMAGEN (requerido)

  source={require('./imagen.jpg')}        // Local

  source={{uri: 'https://...'}}           // Remota

  source={{uri: 'data:image/...'}}        // Base64

  

  // ESTILOS (similares a View)

  style={{

    width: 200,                     // Ancho

    height: 200,                    // Alto

    borderRadius: 10,               // Bordes redondeados

    borderWidth: 2,                 // Borde

    borderColor: '#ccc',            // Color del borde

    backgroundColor: '#f0f0f0',     // Fondo (mientras carga)

    opacity: 0.8,                   // Transparencia

    tintColor: 'red',               // Color de tinte

    resizeMode: 'cover',            // Modo de redimensionado

    overlayColor: 'white',          // Color de superposición

  }}

  

  // COMPORTAMIENTO

  resizeMode="cover"                // 'cover', 'contain', 'stretch', 'repeat', 'center'

  blurRadius={5}                    // Desenfoque (iOS)

  defaultSource={require('./placeholder.jpg')} // Imagen mientras carga

  loadingIndicatorSource={require('./spinner.gif')} // Indicador de carga

  

  // EVENTOS

  onLoad={() => console.log('Imagen cargada')}

  onLoadStart={() => console.log('Comenzando carga')}

  onLoadEnd={() => console.log('Carga terminada')}

  onError={(error) => console.log('Error:', error)}

  onProgress={(event) => {

    const progress = event.nativeEvent.loaded / event.nativeEvent.total;

    console.log(`Progreso: ${Math.round(progress * 100)}%`);

  }}

  

  // ACCESIBILIDAD

  accessible={true}

  accessibilityLabel="Descripción de la imagen"

/>

6.2 Ejemplo: resizeMode en Acción

javascript

const ModosRedimensionado = () => {

  const modos = ['cover', 'contain', 'stretch', 'repeat', 'center'];

  

  return (

    <ScrollView style={styles.container}>

      <Text style={styles.titulo}>Modos de Redimensionado (resizeMode)</Text>

      

      {modos.map((modo) => (

        <View key={modo} style={styles.modoContainer}>

          <Text style={styles.modoTitulo}>

            resizeMode="{modo}"

          </Text>

          

          <View style={styles.contenedorImagen}>

            <Image

              style={[styles.imagenDemo, { resizeMode: modo }]}

              source={{

                uri: 'https://reactnative.dev/img/tiny_logo.png'

              }}

            />

          </View>

          

          <Text style={styles.modoDescripcion}>

            {modo === 'cover' && 'Cubre todo el contenedor, puede recortar'}

            {modo === 'contain' && 'Muestra completa, puede dejar espacios'}

            {modo === 'stretch' && 'Estira para llenar, puede distorsionar'}

            {modo === 'repeat' && 'Repite la imagen (solo iOS)'}

            {modo === 'center' && 'Centra sin redimensionar'}

          </Text>

        </View>

      ))}

    </ScrollView>

  );

};


const styles = StyleSheet.create({

  container: { flex: 1, padding: 20 },

  titulo: { fontSize: 24, fontWeight: 'bold', marginBottom: 20 },

  modoContainer: { marginBottom: 30 },

  modoTitulo: { fontSize: 18, fontWeight: '600', marginBottom: 10 },

  contenedorImagen: {

    width: 200,

    height: 150,

    backgroundColor: '#f0f0f0',

    borderWidth: 1,

    borderColor: '#ddd',

    marginBottom: 10,

  },

  imagenDemo: {

    width: '100%',

    height: '100%',

  },

  modoDescripcion: {

    fontSize: 14,

    color: '#666',

  },

});


🏗️ Paso 7: Diseño con Imágenes

7.1 Layout con Flexbox y Imágenes

javascript

const GaleriaFlexbox = () => {

  return (

    <View style={styles.container}>

      <Text style={styles.titulo}>Galería con Flexbox</Text>

      

      {/* Layout de columnas */}

      <View style={styles.galeria}>

        {/* Fila 1: 2 imágenes */}

        <View style={styles.fila}>

          <Image

            style={styles.imagenColumna}

            source={{ uri: 'https://picsum.photos/200/200?random=1' }}

          />

          <Image

            style={styles.imagenColumna}

            source={{ uri: 'https://picsum.photos/200/200?random=2' }}

          />

        </View>

        

        {/* Fila 2: 1 imagen ancha */}

        <Image

          style={styles.imagenAncha}

          source={{ uri: 'https://picsum.photos/400/200?random=3' }}

        />

        

        {/* Fila 3: 3 imágenes */}

        <View style={styles.fila}>

          <Image

            style={styles.imagenTercera}

            source={{ uri: 'https://picsum.photos/150/150?random=4' }}

          />

          <Image

            style={styles.imagenTercera}

            source={{ uri: 'https://picsum.photos/150/150?random=5' }}

          />

          <Image

            style={styles.imagenTercera}

            source={{ uri: 'https://picsum.photos/150/150?random=6' }}

          />

        </View>

      </View>

    </View>

  );

};


const styles = StyleSheet.create({

  container: {

    flex: 1,

    padding: 20,

  },

  titulo: {

    fontSize: 24,

    fontWeight: 'bold',

    marginBottom: 20,

  },

  galeria: {

    flex: 1,

  },

  fila: {

    flexDirection: 'row',

    justifyContent: 'space-between',

    marginBottom: 10,

  },

  imagenColumna: {

    width: '49%',

    aspectRatio: 1,

    borderRadius: 8,

  },

  imagenAncha: {

    width: '100%',

    height: 200,

    borderRadius: 8,

    marginBottom: 10,

  },

  imagenTercera: {

    width: '32%',

    aspectRatio: 1,

    borderRadius: 8,

  },

});

7.2 Ejemplo: Perfil de Usuario con Imágenes

javascript

const PerfilUsuario = () => {

  return (

    <ScrollView style={styles.container}>

      {/* Header con imagen de fondo */}

      <Image

        style={styles.imagenFondo}

        source={{ uri: 'https://picsum.photos/400/200?blur=2' }}

        blurRadius={3}

      >

        {/* Overlay oscuro */}

        <View style={styles.overlay} />

        

        {/* Contenido del header */}

        <View style={styles.headerContent}>

          {/* Avatar circular */}

          <Image

            style={styles.avatar}

            source={{ uri: 'https://picsum.photos/150/150?random=1' }}

          />

          

          <Text style={styles.nombreUsuario}>Ana García</Text>

          <Text style={styles.bioUsuario}>Desarrolladora React Native</Text>

        </View>

      </Image>

      

      {/* Galería de fotos */}

      <Text style={styles.seccionTitulo}>Mis Fotos</Text>

      <View style={styles.galeriaGrid}>

        {[1, 2, 3, 4, 5, 6, 7, 8, 9].map((num) => (

          <Image

            key={num}

            style={styles.fotoGrid}

            source={{ uri: `https://picsum.photos/200/200?random=${num + 10}` }}

          />

        ))}

      </View>

      

      {/* Mini galería horizontal */}

      <Text style={styles.seccionTitulo}>Destacadas</Text>

      <ScrollView horizontal showsHorizontalScrollIndicator={false}>

        {[1, 2, 3, 4, 5].map((num) => (

          <Image

            key={num}

            style={styles.fotoDestacada}

            source={{ uri: `https://picsum.photos/300/200?random=${num + 20}` }}

          />

        ))}

      </ScrollView>

    </ScrollView>

  );

};


const styles = StyleSheet.create({

  container: { flex: 1, backgroundColor: '#fff' },

  imagenFondo: {

    height: 300,

    justifyContent: 'flex-end',

  },

  overlay: {

    ...StyleSheet.absoluteFillObject,

    backgroundColor: 'rgba(0,0,0,0.4)',

  },

  headerContent: {

    padding: 20,

    alignItems: 'center',

  },

  avatar: {

    width: 120,

    height: 120,

    borderRadius: 60,

    borderWidth: 4,

    borderColor: '#fff',

    marginBottom: 15,

  },

  nombreUsuario: {

    fontSize: 28,

    fontWeight: 'bold',

    color: '#fff',

    marginBottom: 5,

  },

  bioUsuario: {

    fontSize: 16,

    color: '#fff',

    opacity: 0.9,

  },

  seccionTitulo: {

    fontSize: 22,

    fontWeight: '600',

    margin: 20,

    marginBottom: 15,

  },

  galeriaGrid: {

    flexDirection: 'row',

    flexWrap: 'wrap',

    paddingHorizontal: 10,

  },

  fotoGrid: {

    width: '33.33%',

    aspectRatio: 1,

    padding: 2,

  },

  fotoDestacada: {

    width: 250,

    height: 180,

    borderRadius: 12,

    marginHorizontal: 10,

    marginBottom: 20,

  },

});


⚡ Paso 8: Optimización de Imágenes

8.1 Mejores Prácticas para Rendimiento

javascript

const ImagenesOptimizadas = () => {

  return (

    <View style={styles.container}>

      <Text style={styles.titulo}>Optimización de Imágenes</Text>

      

      {/* 1. Tamaños adecuados */}

      <View style={styles.consejo}>

        <Text style={styles.consejoTitulo}>1. Usa tamaños adecuados</Text>

        <Image

          style={[styles.imagenEjemplo, { width: 100, height: 100 }]} // ✅ Correcto

          source={{ uri: 'https://picsum.photos/100/100' }}

        />

        <Text style={styles.consejoMalo}>NO: Cargar 1000x1000 para mostrar 100x100</Text>

      </View>

      

      {/* 2. Indicadores de carga */}

      <View style={styles.consejo}>

        <Text style={styles.consejoTitulo}>2. Usa placeholders</Text>

        <View style={styles.placeholderContainer}>

          <Image

            style={styles.imagenEjemplo}

            source={{ uri: 'https://picsum.photos/200/200?slow=1' }}

            defaultSource={require('./assets/placeholder.jpg')}

          />

        </View>

      </View>

      

      {/* 3. Cache de imágenes */}

      <View style={styles.consejo}>

        <Text style={styles.consejoTitulo}>3. Usa cache apropiado</Text>

        <Image

          style={styles.imagenEjemplo}

          source={{

            uri: 'https://picsum.photos/200/200',

            cache: 'force-cache', // ✅ Cachea la imagen

          }}

        />

      </View>

      

      {/* 4. Lazy loading */}

      <View style={styles.consejo}>

        <Text style={styles.consejoTitulo}>4. Lazy loading para listas</Text>

        <ScrollView>

          {Array.from({ length: 20 }).map((_, index) => (

            <Image

              key={index}

              style={styles.imagenLista}

              source={{ uri: `https://picsum.photos/300/200?random=${index}` }}

              fadeDuration={300} // Animación suave

            />

          ))}

        </ScrollView>

      </View>

    </View>

  );

};

8.2 Checklist de Optimización

javascript

const ChecklistOptimizacion = () => {

  const checklist = [

    { id: 1, texto: 'Redimensionar imágenes al tamaño de visualización', completado: true },

    { id: 2, texto: 'Comprimir imágenes (JPEG para fotos, PNG para gráficos)', completado: true },

    { id: 3, texto: 'Usar WebP cuando sea posible (mejor compresión)', completado: false },

    { id: 4, texto: 'Implementar lazy loading para imágenes fuera de pantalla', completado: true },

    { id: 5, texto: 'Usar placeholders durante la carga', completado: true },

    { id: 6, texto: 'Implementar caché apropiado', completado: false },

    { id: 7, texto: 'Precargar imágenes críticas', completado: true },

    { id: 8, texto: 'Eliminar metadatos EXIF innecesarios', completado: false },

  ];

  

  return (

    <View style={styles.container}>

      <Text style={styles.titulo}>Checklist de Optimización</Text>

      {checklist.map(item => (

        <View key={item.id} style={styles.checkItem}>

          <Text style={item.completado ? styles.checkCompletado : styles.checkPendiente}>

            {item.completado ? '✅' : '⭕'} {item.texto}

          </Text>

        </View>

      ))}

    </View>

  );

};


⚠️ Paso 9: Problemas Comunes y Soluciones

❌ Error: "Image no se muestra"

javascript

// ❌ MAL: Falta dimensiones

<Image source={require('./imagen.jpg')} />


// ✅ BIEN: Especificar width y height

<Image 

  style={{ width: 100, height: 100 }}

  source={require('./imagen.jpg')} 

/>

❌ Error: "Imagen local no encuentra la ruta"

javascript

// SOLUCIÓN: Verificar estructura de carpetas

// Correcto:

source={require('./assets/images/logo.png')}


// Verificar que el archivo existe en:

// proyecto/assets/images/logo.png

❌ Error: "Imagen de URL no carga"

javascript

// SOLUCIÓN 1: Verificar permisos en Android (android/app/src/main/AndroidManifest.xml)

<uses-permission android:name="android.permission.INTERNET" />


// SOLUCIÓN 2: Usar https en lugar de http (iOS requiere https)

// ❌ MAL: http://...

// ✅ BIEN: https://...


// SOLUCIÓN 3: Agregar config para iOS (ios/[proyecto]/Info.plist)

<key>NSAppTransportSecurity</key>

<dict>

    <key>NSAllowsArbitraryLoads</key>

    <true/>

</dict>

❌ Error: "Imagen base64 no válida"

javascript

// SOLUCIÓN: Verificar formato correcto

// Debe incluir data:image/[formato];base64,

<Image

  source={{

    uri: 'data:image/png;base64,iVBORw0KGgoAAAANS...'

  }}

/>


📋 Paso 10: Mejores Prácticas

10.1 Consejos Profesionales

  1. Usa require() para imágenes locales - Se incluyen en el bundle

  2. Especifica siempre width y height - Evita problemas de layout

  3. Usa resizeMode="contain" para imágenes que deben verse completas

  4. Implementa placeholders para mejorar UX durante carga

  5. Optimiza imágenes antes de incluirlas - Reduce tamaño de app

  6. Usa caché apropiado para imágenes remotas frecuentes

  7. Considera usar librerías para necesidades avanzadas:

    • react-native-fast-image - Caché avanzado y performance

    • react-native-image-picker - Selección de imágenes

    • react-native-image-crop-picker - Recorte de imágenes

10.2 Diferencias entre Plataformas

javascript

const ImagenPlataforma = () => (

  <Image

    source={require('./assets/logo.png')}

    style={Platform.select({

      ios: {

        // Estilos específicos iOS

        shadowColor: '#000',

        shadowOffset: { width: 0, height: 2 },

        shadowOpacity: 0.25,

        shadowRadius: 3.84,

      },

      android: {

        // Estilos específicos Android

        elevation: 5,

      },

    })}

  />

);


🎯 Resumen: ¿Cuándo usar cada tipo?

Tipo

Ventajas

Desventajas

Mejor para

Local (require)

⚡ Carga instantánea, 💾 Sin dependencia de red

📦 Aumenta tamaño de app

Íconos, imágenes de la UI

URL (uri)

📦 No aumenta tamaño de app, 🔄 Fácil de actualizar

🌐 Requiere conexión, ⏱️ Tiempo de carga

Imágenes dinámicas, contenido remoto

Base64

📱 Sin archivos externos, 🔒 Funciona sin red

📈 Tamaño mayor, 🚫 No escalable

Imágenes muy pequeñas, gráficos simples


🎬 Próximo Tutorial

En el siguiente video aprenderemos:

  • Componente Button y TouchableOpacity

  • Diferentes tipos de botones

  • Estilización avanzada de botones

  • Manejo de eventos de toque


✅ ¡Ahora dominas el componente Image! Puedes mostrar imágenes desde cualquier fuente y optimizarlas para el mejor rendimiento. Practica creando galerías, perfiles y interfaces ricas en imágenes.


Comentarios

Entradas más populares de este blog

18. Visualizar nuestros componentes limpios con StyleSheet

Tema: 23. Justify Content en Flexbox para Column (Columna) en React Nativ