7.4-36. Retroalimentación al tocar el botón

 

Retroalimentación Visual al Tocar Botones en React Native

Una buena UX requiere que los usuarios siempre sepan cuando interactúan con elementos táctiles. Veamos cómo implementar feedback visual efectivo en nuestros botones.

🔍 El Problema: Falta de Feedback

Por defecto, muchos componentes no muestran cambios visuales al ser presionados:

jsx
<Pressable onPress={() => console.log('Pressed!')}>
  <Text>Mi Botón</Text>
</Pressable>

🎯 Soluciones Comparadas

1. Usando TouchableOpacity (Alternativa)

jsx
<TouchableOpacity 
  activeOpacity={0.7} // Valor entre 0 (transparente) y 1 (opaco)
  onPress={handlePress}
>
  <Text>Botón con Opacidad</Text>
</TouchableOpacity>

Pros:

  • Sencillo de implementar

  • Efecto visual inmediato

Contras:

  • Menos personalizable

  • No es el componente recomendado actualmente

2. Usando Pressable (Recomendado)

jsx
<Pressable
  style={({ pressed }) => [
    styles.button,
    { opacity: pressed ? 0.7 : 1 }
  ]}
  onPress={handlePress}
>
  <Text>Botón Moderno</Text>
</Pressable>

Ventajas:

  • Mayor control sobre los estados

  • Permite animaciones complejas

  • Componente oficial recomendado

🎨 Efectos Avanzados con Pressable

Cambio de Color al Presionar

jsx
<Pressable
  style={({ pressed }) => [
    styles.button,
    { 
      backgroundColor: pressed ? '#4A306D' : '#65558F',
      transform: pressed ? [{ scale: 0.95 }] : [{ scale: 1 }]
    }
  ]}
>

Efecto de "Aplastamiento"

jsx
{
  transform: [
    { scale: pressed ? 0.95 : 1 },
    { translateY: pressed ? 2 : 0 }
  ]
}

Combinación Múltiple

jsx
<Pressable
  style={({ pressed }) => [
    styles.button,
    {
      opacity: pressed ? 0.8 : 1,
      backgroundColor: pressed ? '#4A306D' : '#65558F',
      transform: [
        { scale: pressed ? 0.98 : 1 },
        { translateY: pressed ? 1 : 0 }
      ]
    }
  ]}
>

💡 Implementación en Nuestro FAB

typescript
// components/FAB.tsx
export const FAB = ({ label, onPress, position = 'right' }: FABProps) => {
  return (
    <Pressable
      style={({ pressed }) => [
        styles.button,
        position === 'right' ? styles.positionRight : styles.positionLeft,
        {
          opacity: pressed ? 0.7 : 1,
          transform: [{ scale: pressed ? 0.95 : 1 }]
        }
      ]}
      onPress={onPress}
    >
      <Text style={styles.label}>{label}</Text>
    </Pressable>
  );
};

📱 Efectos Específicos por Plataforma

Android e iOS manejan las interacciones táctiles diferente:

typescript
// Para Android (efecto ripple nativo)
<Pressable
  android_ripple={{ color: 'rgba(255,255,255,0.2)', borderless: false }}
  style={/* ... */}
>
typescript
// Para iOS (zoom suave)
<Pressable
  style={({ pressed }) => ({
    transform: [{ scale: pressed ? 0.95 : 1 }],
    opacity: pressed ? 0.7 : 1
  })}
>

📌 Buenas Prácticas

  1. Mantén la consistencia: Usa los mismos efectos en toda la app

  2. No exageres: Animaciones sutiles > efectos exagerados

  3. Prueba en dispositivos reales: Los emuladores no siempre reflejan bien las interacciones táctiles

  4. Considera accesibilidad: Usa contrastes claros entre estados

🚀 Ejemplo Completo

typescript
interface FABProps {
  label: string;
  onPress?: () => void;
  position?: 'left' | 'right';
}

export const FAB = ({ label, onPress, position = 'right' }: FABProps) => {
  return (
    <Pressable
      style={({ pressed }) => [
        styles.baseButton,
        positionStyles[position],
        {
          opacity: pressed ? 0.7 : 1,
          transform: [{ scale: pressed ? 0.95 : 1 }],
          shadowOpacity: pressed ? 0.2 : 0.3,
          elevation: pressed ? 3 : 5
        }
      ]}
      onPress={onPress}
      android_ripple={{ color: 'rgba(255,255,255,0.2)', borderless: true }}
    >
      <Text style={styles.label}>{label}</Text>
    </Pressable>
  );
};

const styles = StyleSheet.create({
  baseButton: {
    position: 'absolute',
    bottom: 20,
    backgroundColor: '#65558F',
    padding: 20,
    borderRadius: 15,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 4 },
    shadowRadius: 4,
  },
  positionRight: { right: 20 },
  positionLeft: { left: 20 },
  label: { color: 'white', fontSize: 20 }
});

¿Qué tipo de feedback visual prefieres implementar en tus apps? ¡Compártelo en los comentarios!

Comentarios

Entradas más populares de este blog

4.2-12. Componentes esenciales

7.5-10. ¿Como funcionan los estilos en React Native?

7.1-19. Creación de estilos