Usando SafeAreaView
, Estilos con StyleSheet
y Pressable
en React Native
En este tutorial, aprenderemos cómo organizar la estructura de una aplicación en React Native usando SafeAreaView
como contenedor principal, crear pantallas o “screens” dentro de una carpeta src
, y cómo gestionar los estilos utilizando StyleSheet
. Además, exploraremos cómo usar el componente Pressable
en lugar del antiguo Button
, que ha sido deprecado.
1. Usando SafeAreaView
como Contenedor
Para que la interfaz de usuario se vea bien en dispositivos con diferentes tamaños de pantalla y márgenes, React Native nos ofrece el componente SafeAreaView
. Este componente garantiza que los elementos que agregamos dentro de él no se superpongan con áreas no interactivas como la barra de estado o la barra de navegación.
El código básico se vería así:
import React from 'react';
import { SafeAreaView } from 'react-native';
import { HelloWorldScreen } from './src/presentation/screens/HelloWorldScreen';
const App = () => {
return (
<SafeAreaView style={{ flex: 1, backgroundColor: '#000' }}>
<HelloWorldScreen />
</SafeAreaView>
);
};
export default App;
Aquí, SafeAreaView
actúa como el contenedor principal, y dentro de él colocamos el componente HelloWorldScreen
. Establecemos flex: 1
para que ocupe todo el espacio disponible, y un backgroundColor
de #000
(negro) para darle un fondo oscuro a nuestra pantalla.
2. Estructura de Archivos: Carpetas y Pantallas
Vamos a organizar el proyecto para que sea más escalable y mantenible. Crearemos una carpeta src
y dentro de ella una subcarpeta presentation
que contendrá nuestras pantallas (screens
). La pantalla HelloWorldScreen
tendrá el siguiente contenido:
// src/presentation/screens/HelloWorldScreen.tsx
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
interface Props {
name?: string;
}
export const HelloWorldScreen = ({ name = 'World' }: Props) => {
return (
<View style={styles.container}>
<Text style={styles.title} numberOfLines={1} ellipsizeMode="tail">
Hola, {name}
</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'purple',
},
title: {
fontSize: 45,
textAlign: 'center',
color: 'black',
padding: 20,
},
});
3. Estilos con StyleSheet.create
En React Native, los estilos se definen utilizando StyleSheet.create
, que optimiza el rendimiento al evitar recalcular los estilos en cada renderizado. Al utilizar StyleSheet.create
, estamos creando un objeto de estilos que React Native puede manejar de forma más eficiente.
¿Qué hace cada parte del código?
-
container
: Es el estilo que se aplica al componenteView
. A través deflex: 1
, estamos diciendo que este componente debe ocupar todo el espacio disponible. También le asignamos un color de fondopurple
y centramos su contenido conjustifyContent: 'center'
. -
title
: Este estilo se aplica al componenteText
. Aquí definimos:fontSize: 45
: Establece el tamaño del texto.textAlign: 'center'
: Centra el texto horizontalmente.color: 'black'
: Establece el color del texto a negro.padding: 20
: Añade espacio alrededor del texto.
4. Uso de Propiedades en el Componente Text
En el componente Text
, podemos ver que usamos las propiedades numberOfLines
y ellipsizeMode
:
numberOfLines={1}
: Limita el número de líneas del texto a una sola. Si el texto es más largo de lo que puede caber, se cortará.ellipsizeMode="tail"
: Cuando el texto se corta, agrega puntos suspensivos (”…”) al final para indicar que el texto ha sido truncado.
5. ¿Por qué Definir el color
en .title
y No en el container
?
El color
de nuestro texto se establece en el estilo .title
en lugar de en el estilo container
porque queremos que solo el texto tenga un color específico. El container
define el estilo del contenedor (fondo, flex, alineación, etc.), pero no debe influir en el color del contenido. Esto sigue el principio de separación de responsabilidades, donde cada estilo debe afectar únicamente lo que corresponde a ese componente.
6. Cambiar Estilos Según la Plataforma
Podemos ajustar los estilos en función de la plataforma en la que se esté ejecutando la aplicación. Para hacerlo, usamos Platform.OS
. A continuación, te mostramos cómo cambiar el color del texto dependiendo de si estamos en Android o en iOS.
import React from 'react';
import { StyleSheet, Text, View, Platform } from 'react-native';
interface Props {
name?: string;
}
export const HelloWorldScreen = ({ name = 'World' }: Props) => {
return (
<View style={styles.container}>
<Text style={[styles.title, { color: Platform.OS === 'android' ? 'green' : 'blue' }]}>
Hola, {name}
</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'purple',
},
title: {
fontSize: 45,
textAlign: 'center',
padding: 20,
},
});
Aquí estamos usando un condicional dentro de los estilos: si la plataforma es Android, el color del texto será verde; si es iOS, el color será azul.
7. Usando Pressable
en Lugar de Button
El componente Button
en React Native ha sido deprecado, por lo que ahora se recomienda usar Pressable
para manejar interacciones táctiles. A continuación, te mostramos cómo usarlo para implementar un contador que cambie su valor al presionar el botón.
import React, { useState } from 'react';
import { Pressable, Text, View, StyleSheet } from 'react-native';
export const CounterButton = () => {
const [count, setCount] = useState(0);
const handlePress = () => {
setCount(count + 1);
};
const handleLongPress = () => {
setCount(0);
};
return (
<View style={styles.container}>
<Text style={styles.title}>Contador: {count}</Text>
<Pressable
onPress={handlePress}
onLongPress={handleLongPress}
style={({ pressed }) => [
styles.button,
{ backgroundColor: pressed ? 'red' : 'green' },
]}
>
<Text style={styles.buttonText}>Presiona aquí</Text>
</Pressable>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'purple',
},
title: {
fontSize: 30,
color: 'white',
marginBottom: 20,
},
button: {
padding: 10,
borderRadius: 5,
},
buttonText: {
color: 'white',
fontSize: 20,
},
});
Explicación de Pressable
onPress
: Se activa cuando el usuario hace un click normal sobre el botón.onLongPress
: Se activa cuando el usuario mantiene presionado el botón durante más tiempo.style={({ pressed }) => [...]}
: Esta es una función que recibe un objetopressed
, el cual nos indica si el botón está siendo presionado o no. Usamos este valor para cambiar el color de fondo del botón. Sipressed
estrue
, el fondo será rojo, de lo contrario, será verde.
Podes ver mas componentes y sus propidades en la documentacion oficial de react native