El componente ScrollView en React Native es un contenedor que permite desplazar el contenido que supera el tamaño de la pantalla. A diferencia de FlatList, ScrollView renderiza todo el contenido de una vez, lo que es óptimo para pequeñas cantidades de datos, formularios y pantallas con altura conocida. Según la React Native Docs, 2024, ScrollView admite desplazamiento vertical y horizontal, el evento onScroll, control programático de posición y gestos de zoom. El componente se renderiza en UIScrollView nativo en iOS y ScrollView en Android.
Puntos clave
ScrollView es un componente de React Native que envuelve su contenido en un contenedor desplazable. Si el contenido supera los límites de la pantalla, el usuario puede desplazarse vertical u horizontalmente. ScrollView renderiza todos los elementos hijos al montarse, independientemente de si son visibles en pantalla o no.
A diferencia de FlatList, que renderiza solo los elementos visibles (renderizado perezoso), ScrollView crea todas las vistas nativas de inmediato. Esto hace que ScrollView sea conveniente para formularios, páginas de configuración, tarjetas de producto en una sola pantalla — en cualquier lugar donde la cantidad de elementos hijos sea pequeña (hasta 20-30) o su cantidad exacta se desconozca de antemano.
Según la React Native Using ScrollView, 2024, ScrollView admite desplazamiento anidado (por ejemplo, ScrollView dentro de ScrollView), efecto de rebote al alcanzar el borde, indicadores de desplazamiento, posicionamiento snap y manejo de gestos. En iOS, ScrollView agrega automáticamente el padding de SafeArea mediante contentInsetAdjustmentBehavior.
ScrollView proporciona un conjunto rico de propiedades para controlar el comportamiento del desplazamiento, la apariencia y la interactividad. Veamos los grupos clave: control de desplazamiento, ajustes visuales, eventos y características específicas de la plataforma.
horizontal — cambia la dirección de desplazamiento de vertical (predeterminada) a horizontal. scrollEnabled — deshabilita el desplazamiento cuando sea necesario. showsVerticalScrollIndicator y showsHorizontalScrollIndicator controlan la visualización de los indicadores de desplazamiento. bounces (iOS) activa/desactiva el efecto de rebote al alcanzar el borde del contenido.
El evento principal es onScroll, que se dispara en cada desplazamiento y pasa un objeto con nativeEvent que contiene contentOffset (posición actual), contentSize (tamaño del contenido), layoutMeasurement (tamaño del área visible). onMomentumScrollEnd se dispara después de que se completa el desplazamiento por inercia. onScrollEndDrag — cuando el usuario levanta el dedo de la pantalla. Estos eventos se utilizan para implementar desplazamiento infinito, efectos de paralaje y carga diferida.
ScrollView proporciona métodos para el control programático mediante ref: scrollTo({x, y, animated}) desplaza a las coordenadas especificadas, scrollToEnd({animated}) — desplaza al final del contenido, flashScrollIndicators() — muestra temporalmente los indicadores de desplazamiento.
const scrollRef = useRef(null);
// Scroll to top
scrollRef.current.scrollTo({ x: 0, y: 0, animated: true });
// Scroll to end
scrollRef.current.scrollToEnd({ animated: true });
El control programático del desplazamiento se utiliza a menudo en chats (desplazamiento automático al último mensaje), formularios (desplazamiento a un campo con error) y carruseles (desplazamiento programático).
Elegir entre ScrollView y FlatList es una de las decisiones arquitectónicas clave en React Native. Ambos componentes proporcionan desplazamiento, pero utilizan estrategias de renderizado fundamentalmente diferentes. ScrollView renderiza todo de una vez, FlatList — solo los elementos visibles.
| Característica | ScrollView | FlatList |
|---|---|---|
| Renderizado | Todos los elementos de una vez | Solo visibles + buffer |
| Rendimiento | Degrada con 30+ elementos | Estable en cualquier cantidad |
| Contenido | Cualquier componente (formularios, tarjetas) | Elementos uniformes de un array |
| Tamaño de datos | Pequeño y mediano (hasta 30 elementos) | Grande e ilimitado |
| Desplazamiento horizontal | Sí (prop horizontal) | Sí (horizontal) |
| Secciones | No (renderiza tal cual) | SectionList para secciones |
Regla de selección: ScrollView — para pantallas donde la cantidad de elementos hijos se conoce y no supera 20-30 (perfil de usuario, formulario de configuración, página de producto). FlatList — para listas con potencialmente muchos elementos (feed de noticias, catálogo de productos, mensajes de chat). Si el contenido es heterogéneo (encabezado, formulario, tarjeta, pie de página) — ScrollView es preferible ya que FlatList espera elementos uniformes.
ScrollView admite desplazamiento horizontal mediante la prop horizontal, lo que lo hace ideal para carruseles, galerías de imágenes, pestañas y listas horizontales. Cuando se combina con la prop pagingEnabled (iOS) o snapToInterval, ScrollView se convierte en un componente para navegación por páginas.
La propiedad horizontal cambia la dirección de desplazamiento. pagingEnabled (iOS) activa el desplazamiento por páginas, donde el desplazamiento se detiene solo en los límites de los elementos. snapToInterval establece el paso de snap en píxeles para ambas plataformas.
const ImageCarousel = ({ images }) => (
<ScrollView
horizontal
pagingEnabled
showsHorizontalScrollIndicator={false}
onMomentumScrollEnd={handlePageChange}
>
{images.map((img, index) => (
<Image
key={index}
source={{ uri: img }}
style={{ width: SCREEN_WIDTH, height: 250 }}
/>
))}
</ScrollView>
);
En este carrusel, pagingEnabled ajusta automáticamente el desplazamiento a los límites de cada imagen. onMomentumScrollEnd permite actualizar el indicador de página actual. Este carrusel funciona de forma nativa y admite desplazamiento por inercia.
Para pasos de snap no estándar, use snapToInterval (tamaño del paso en píxeles) y snapToAlignment (start, center, end). Con snapToOffsets puede especificar un array de posiciones específicas para el snap. Esto es útil para listas horizontales con tarjetas de diferentes tamaños.
Veamos dos escenarios típicos: una pantalla con formulario (desplazamiento vertical) y una lista horizontal de categorías. Ambos usan ScrollView con diferentes propiedades para un comportamiento óptimo.
Una página de edición de perfil contiene elementos heterogéneos: avatar, varios campos de entrada, interruptores y un botón de guardar. ScrollView permite desplazar toda la página en su conjunto, en lugar de cada bloque por separado.
const ProfileScreen = () => (
<ScrollView
contentContainerStyle={styles.container}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
>
<AvatarPicker />
<TextInput placeholder="Name" />
<TextInput placeholder="Email" />
<TextInput placeholder="About me" multiline />
<SwitchRow label="Notifications" />
<Button title="Save" />
</ScrollView>
);
La propiedad keyboardShouldPersistTaps: 'handled' permite desplazarse e interactuar con el formulario cuando el teclado está abierto. contentContainerStyle aplica padding a todo el contenido. Este patrón se utiliza en todas las pantallas con formularios en React Native.
Para navegar por categorías (chats, filtros, pestañas), se utiliza un ScrollView horizontal con chips. Este componente se encuentra comúnmente en aplicaciones de marketplaces y redes sociales.
const CategoryChips = ({ categories, selected, onSelect }) => (
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.chipContainer}
>
{categories.map((cat) => (
<Chip
key={cat.id}
label={cat.name}
isSelected={selected === cat.id}
onPress={() => onSelect(cat.id)}
/>
))}
</ScrollView>
);
Un ScrollView horizontal con el indicador desactivado es el estándar para las tiras de categorías. Cada chip es un componente separado con estado de selección. La propiedad showsHorizontalScrollIndicator: false elimina la barra de desplazamiento, lo que coincide con las expectativas de los usuarios de aplicaciones móviles.
Preguntas frecuentes
ScrollView es adecuado para pequeñas cantidades de datos (hasta 20-30 elementos) y contenido heterogéneo (formularios, perfiles, pantallas de configuración). Elija FlatList para listas largas uniformes — feed de noticias, catálogo de productos, mensajes.
Use el evento onScroll con onScrollEndDrag o onMomentumScrollEnd. La posición vertical actual está en nativeEvent.contentOffset.y. Para rendimiento, use ScrollEventThrottle (iOS) para ajustar la frecuencia de llamada de onScroll.
ScrollView renderiza todos los elementos al montarse, creando vistas nativas para cada uno. Con 50+ elementos en pantalla, la carga de memoria y el hilo JS crecen, causando caídas de fotogramas. Para tales casos, use FlatList con renderizado diferido.
Establezca bounces={false}. Esta prop solo funciona en iOS y desactiva el efecto elástico al alcanzar el borde de ScrollView. En Android, no hay efecto de rebote por defecto, por lo que la prop se ignora.
ScrollView no admite desplazamiento infinito de forma nativa. Sin embargo, puede combinar onScroll con verificación de proximidad al borde inferior (contentOffset.y + altura de pantalla >= contentSize.height) y agregar elementos al estado. Para volúmenes grandes, use FlatList con onEndReached.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también