Олег Марков
Работа со ScrollView в React Native
Введение
Реализация удобного прокручиваемого интерфейса — одна из самых частых задач в мобильной разработке на React Native. От длинных списков до сложных форм, когда контент не помещается на экране, на помощь приходит компонент ScrollView. Его правильное применение помогает сделать приложение отзывчивым, интуитивно понятным и современным.
В статье я расскажу, как использовать ScrollView в React Native, раскрою основные возможности, объясню, как управлять прокруткой и где стоит быть внимательным из-за ограничений. На практике покажу примеры использования, а также рассмотрим типичные ошибки и способы их избежать.
Что такое ScrollView и когда его применять
ScrollView
— базовый компонент React Native для вертикальной (и горизонтальной) прокрутки контента, размер которого превышает размеры экрана пользователя. В отличие от компонент FlatList или SectionList, используемых для отображения длинных (часто динамических) списков, ScrollView идеально подходит для случаев, когда у вас:
- Небольшое количество компонентов, которые нужно разместить друг за другом (например, форма или карточки).
- Контент не требует динамической подгрузки во время прокрутки.
- Вся вложенная разметка известна заранее.
ScrollView — это компонент React Native, позволяющий отображать контент, который не помещается на экране, с возможностью прокрутки. Важно уметь правильно использовать ScrollView, чтобы избежать проблем с производительностью, особенно при отображении большого количества контента. Необходимо также понимать, как настраивать стили, обрабатывать события прокрутки и использовать другие компоненты, такие как FlatList, для более эффективного отображения списков. Если вы хотите детальнее погрузиться в работу со ScrollView и другими компонентами React Native, — приходите на наш большой курс React Native и Expo Router. На курсе 184 уроков и 11 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.
Главные отличия ScrollView от FlatList
ScrollView
загружает в память все вложенные компоненты сразу, поэтому подходит только для небольших объемов данных.- При отображении длинных или динамических списков выбирайте FlatList или SectionList, так как они рендерят только видимую часть контента.
Основные свойства ScrollView
Давайте посмотрим на главные props (свойства), которые чаще всего используются:
- horizontal — включает горизонтальную прокрутку.
- showsVerticalScrollIndicator / showsHorizontalScrollIndicator — управляют видимостью стандартных полос прокрутки.
- contentContainerStyle — позволяет стилизовать внутреннюю обертку компонента.
- onScroll — реагирует на событие прокрутки.
- refreshControl — позволяет добавить функционал "потяни, чтобы обновить" (pull to refresh).
- pagingEnabled — включает режим постраничной прокрутки, как у каруселей.
- scrollEnabled — позволяет полностью отключить прокрутку.
- keyboardShouldPersistTaps — определяет, должны ли касания сохраняться при открытой клавиатуре.
Теперь давайте разберемся, как это применяется на практике.
Пример базового использования ScrollView
Смотрите, я покажу простой пример. Вот как разместить несколько компонентов так, чтобы они прокручивались вертикально по мере заполнения экрана:
import React from 'react';
import { ScrollView, View, Text, StyleSheet } from 'react-native';
const App = () => {
return (
<ScrollView
style={styles.container}
contentContainerStyle={styles.contentContainer}
showsVerticalScrollIndicator={false} // Скрываем стандартную полосу скролла
>
<Text style={styles.title}>Список элементов</Text>
{/* Несколько элементов, которые выходят за пределы экрана */}
{Array.from({ length: 20 }).map((_, idx) => (
<View key={idx} style={styles.item}>
<Text>Элемент {idx + 1}</Text>
</View>
))}
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f6f6f6'
},
contentContainer: {
padding: 20
},
title: {
fontSize: 22,
marginBottom: 15
},
item: {
backgroundColor: '#e5e5e5',
padding: 20,
marginBottom: 10,
borderRadius: 10
}
});
export default App;
В этом примере прокручивается список из 20 элементов, каждый из которых — отдельный View. Прокрутка активируется автоматически, когда контента становится больше, чем помещается на экране.
Как создать горизонтальный ScrollView
Иногда вам нужно реализовать горизонтальную прокрутку, например, для списка карточек. Здесь все просто: добавьте свойство horizontal.
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={{ paddingHorizontal: 15, paddingVertical: 20 }}
>
{/* Здесь можно вывести карточки или изображения */}
</ScrollView>
Компоненты внутри ScrollView теперь можно прокручивать по горизонтали.
Управление стилем содержимого через contentContainerStyle
Обратите внимание: если вы хотите задать внутренние отступы или выравнивание всего контента, используйте contentContainerStyle
, а не style самого ScrollView:
<ScrollView
contentContainerStyle={{
alignItems: 'center', // Все дочерние элементы будут по центру
paddingBottom: 40 // Дополнительный отступ снизу
}}
>
{/* Ваша разметка */}
</ScrollView>
Контроль скролла программно с помощью ref
Иногда нужно прокрутить ScrollView к определенному месту по событию. Для этого используем ref и методы прокрутки.
Пример: прокрутка вниз при клике на кнопку
import React, { useRef } from 'react';
import { ScrollView, View, Button } from 'react-native';
const App = () => {
const scrollViewRef = useRef(null);
// Функция для прокрутки в самый низ
const scrollToEnd = () => {
scrollViewRef.current?.scrollToEnd({ animated: true }); // scrollToEnd - метод ScrollView
};
return (
<>
<Button title="Прокрутить вниз" onPress={scrollToEnd} />
<ScrollView ref={scrollViewRef}>
{/* Большой набор элементов */}
</ScrollView>
</>
);
};
Методы, которые доступны:
scrollTo
: прокрутка к конкретной координате (x, y).scrollToEnd
: прокрутка в самый конец.
Все эти методы можно анимировать (animated: true
).
Отслеживание положения скролла: onScroll
Часто возникает задача узнать текущую позицию прокрутки — например, чтобы отобразить кнопку "Вверх", когда пользователь немного пролистал экран.
Вот как это реализуется:
<ScrollView
onScroll={({ nativeEvent }) => {
if (nativeEvent.contentOffset.y > 50) {
// Пользователь прокрутил более чем на 50 пикселей
// Можно показать плавающую кнопку
}
}}
scrollEventThrottle={16} // ограничивает частоту onScroll, 16мс — около 60 FPS
>
{/* Контент */}
</ScrollView>
Параметр scrollEventThrottle
задает, как часто вызывается обработчик onScroll. Чем меньше значение, тем выше частота, но и нагрузка на JS-поток выше.
"Потяни, чтобы обновить" (Pull to refresh)
В ScrollView легко добавить стандартную для мобильных приложений функцию "потяни вниз — обнови".
import { ScrollView, RefreshControl } from 'react-native';
import React, { useState } from 'react';
const App = () => {
const [refreshing, setRefreshing] = useState(false);
const onRefresh = () => {
setRefreshing(true);
// Здесь симуляция загрузки данных
setTimeout(() => setRefreshing(false), 2000);
};
return (
<ScrollView
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}
>
{/* Ваши компоненты */}
</ScrollView>
);
};
RefreshControl
интегрирует pull-to-refresh с текущим состоянием (refreshing) и обработчиком обновления.
Клавиатура и прокрутка: keyboardShouldPersistTaps
Если в ScrollView много инпутов, и вы хотите, чтобы нажатие вне клавиатуры закрывало ее, установите keyboardShouldPersistTaps="handled"
или "always"
.
<ScrollView keyboardShouldPersistTaps="handled">
{/* Инпуты и другие элементы */}
</ScrollView>
Это поможет управлять поведением клавиатуры при скролле и тапах по области ScrollView.
Оптимизация производительности и ограничения ScrollView
Когда не стоит использовать ScrollView?
- Если у вас может быть большая коллекция компонентов (десятки-сотни элементов), используйте FlatList.
- ScrollView держит в DOM все дочерние компоненты одновременно, что может привести к лагам и падению приложения при большом объеме данных.
Советы по оптимизации
- Ограничивайте количество элементов внутри ScrollView.
- Используйте FlatList для списков, если количество элементов превышает 30-50.
- Не забудьте настроить
scrollEventThrottle
, если используете onScroll.
Способы стилизации ScrollView
Вы можете применить любые CSS-подобные стили, но учитывайте разницу между свойствами style у ScrollView и contentContainerStyle.
style
— отвечает за позиционирование и внешний вид самого ScrollView.contentContainerStyle
— за стили внутренней обертки, внутри которой размещаются все дочерние элементы.
Практические советы
- Чтобы добавить отступ внизу, используйте
contentContainerStyle: { paddingBottom: XX }
- Для центрирования контента —
alignItems: 'center'
внутри contentContainerStyle. - Используйте горизонтальный ScrollView только там, где это действительно нужно для UX.
Заключение
ScrollView — мощный, но простой в использовании инструмент React Native. С его помощью вы можете создавать скроллируемые интерфейсы как по вертикали, так и по горизонтали, программно управлять прокруткой и внедрять привычные для пользователя паттерны мобильных приложений. Однако при увеличении количества элементов переходите к FlatList или SectionList для повышения производительности.
Работа со ScrollView и понимание всех его нюансов это не все, что нужно знать для работы с React Native. На нашем курсе React Native и Expo Router вы найдете все необходимые знания и навыки для создания профессиональных React Native приложений. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир React Native прямо сегодня.
Частозадаваемые технические вопросы по теме и ответы
Как реализовать плавную прокрутку к конкретному элементу внутри ScrollView?
Чтобы прокрутить ScrollView к определенному элементу, необходимо получить координаты этого элемента с помощью метода measure
, а затем вызвать scrollTo
:
// Допустим, у вас есть ref на View элемента внутри ScrollView
elementRef.current.measure((fx, fy, width, height, px, py) => {
scrollViewRef.current.scrollTo({ y: py, animated: true });
});
Почему прокрутка ScrollView иногда лагает при большом количестве элементов?
ScrollView рендерит все дочерние компоненты вместе, что вызывает лаги при десятках и сотнях элементов. Для динамических списков, где количество элементов может быть большим, лучше использовать FlatList или SectionList.
Как убрать отскок скролла (overscroll effect) на iOS?
Можно указать свойство bounces={false}
, чтобы отключить стандартный отскок:
<ScrollView bounces={false}>
{/* Контент */}
</ScrollView>
Как сделать так, чтобы клавиатура не перекрывала поля ввода внутри ScrollView?
Используйте компонент KeyboardAvoidingView
с правильно заданным поведением:
import { KeyboardAvoidingView } from 'react-native';
<KeyboardAvoidingView behavior="padding" style={{ flex: 1 }}>
<ScrollView>
{/* Input поля */}
</ScrollView>
</KeyboardAvoidingView>
Как реализовать "прыгающую" прокрутку (snap to interval) в горизонтальном ScrollView?
Можно использовать свойство snapToInterval
, чтобы реализовать свайпы по карточкам одинаковой ширины:
<ScrollView horizontal snapToInterval={ширинаКарточки} decelerationRate="fast">
{/* Ваши элементы */}
</ScrollView>
Обязательно проверьте на Android и iOS для консистентного UX.
Постройте личный план изучения React-native до уровня Middle — бесплатно!
React-native — часть карты развития Mobile
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по React-native
Лучшие курсы по теме

React Native и Expo Router
Антон Ларичев
Основы JavaScript
Антон Ларичев