Компонентът ScrollView в React Native — контейнер с възможност за скролване на съдържание, което надвишава размерите на екрана. За разлика от FlatList, ScrollView рендерира цялото съдържание наведнъж, което е оптимално за малки количества данни, формуляри и екрани с известна височина. Според React Native Docs, 2024, ScrollView поддържа вертикално и хоризонтално скролване, събитие onScroll, програмно управление на позицията и жестове за мащабиране. Компонентът се рендерира като нативен UIScrollView на iOS и ScrollView на Android.
Основни точки
ScrollView — е компонент React Native, който обвива съдържанието си в скролиращ контейнер. Ако съдържанието надхвърля границите на екрана, потребителят може да го скролва вертикално или хоризонтално. ScrollView рендерира всички дъщерни елементи при монтиране, независимо дали са видими на екрана или не.
За разлика от FlatList, който рендерира само видимите елементи (lazy rendering), ScrollView създава всички нативни графични елементи наведнъж. Това прави ScrollView удобен за формуляри, страници с настройки, карти на продукти на един екран — навсякъде, където броят на дъщерните елементи е малък (до 20-30) или точният им брой не е известен предварително.
Според React Native Using ScrollView, 2024, ScrollView поддържа вложено скролване (напр. ScrollView вътре в ScrollView), ефект на отскачане при достигане на ръба, индикатори за скролване, фиксиране на позиция (snap) и обработка на жестове. На iOS ScrollView автоматично добавя разстояние под SafeArea чрез contentInsetAdjustmentBehavior.
ScrollView предоставя богат набор от свойства за управление на поведението на скролване, външния вид и интерактивността. Нека разгледаме ключовите групи: управление на скролването, визуални настройки, събития и платформени характеристики.
horizontal — превключва посоката на скролване от вертикална (по подразбиране) на хоризонтална. scrollEnabled — изключва скролването при необходимост. showsVerticalScrollIndicator и showsHorizontalScrollIndicator управляват показването на индикаторите за скролване. bounces (iOS) включва/изключва ефекта на отскачане при достигане на ръба на съдържанието.
Основното събитие — onScroll, което се извиква при всяко скролване и предава обект с nativeEvent, съдържащ contentOffset (текуща позиция), contentSize (размер на съдържанието), layoutMeasurement (размер на видимата област). onMomentumScrollEnd се извиква след завършване на инерционното скролване. onScrollEndDrag — когато потребителят е пуснал екрана. Тези събития се използват за реализиране на безкрайно скролване, паралакс и мързеливо зареждане.
ScrollView предоставя методи за програмно управление чрез референция: scrollTo({x, y, animated}) скролва до посочените координати, scrollToEnd({animated}) — до края на съдържанието, flashScrollIndicators() — временно показва индикаторите за скролване.
const scrollRef = useRef(null);
// Скрол до горе
scrollRef.current.scrollTo({ x: 0, y: 0, animated: true });
// Скрол до края
scrollRef.current.scrollToEnd({ animated: true });
Програмното управление на скролването често се използва в чатове (автоматично скролване до последното съобщение), формуляри (скролване до полето с грешка) и карусели (програмно скролване).
Изборът между ScrollView и FlatList — едно от ключовите архитектурни решения в React Native. И двата компонента осигуряват скролване, но използват коренно различни стратегии за рендериране. ScrollView рендерира всичко наведнъж, FlatList — само видимите елементи.
| Характеристика | ScrollView | FlatList |
|---|---|---|
| Рендериране | Всички елементи наведнъж | Само видими + буфер |
| Производителност | Намалява при 30+ елемента | Стабилна при всяко количество |
| Съдържание | Всякакви компоненти (формуляри, карти) | Хомогенни елементи от масив |
| Размер на данни | Малък и среден (до 30 елемента) | Голям и неограничен |
| Хоризонтален скрол | Да (свойство horizontal) | Да (horizontal) |
| Секции | Не (рендерира както е) | SectionList за секции |
Правило за избор: ScrollView — за екрани, където броят на дъщерните елементи е известен и не надвишава 20-30 (потребителски профил, формуляр за настройки, страница на продукт). FlatList — за списъци с потенциално голям брой елементи (новопоток, каталог на продукти, съобщения в чат). Ако съдържанието е разнородно (заглавие, формуляр, карта, футър) — ScrollView е за предпочитане, тъй като FlatList очаква хомогенни елементи.
ScrollView поддържа хоризонтално скролване чрез свойството horizontal, което го прави идеален за карусели, галерии с изображения, раздели и хоризонтални списъци. В комбинация със свойството pagingEnabled (iOS) или snapToInterval, ScrollView се превръща в компонент за навигация по страници.
Свойството horizontal превключва посоката на скролване. pagingEnabled (iOS) включва скролване по страници, при което скролът спира само на границите на елементите. snapToInterval задава стъпката на захващане в пиксели за двете платформи.
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>
);
В това карусело pagingEnabled автоматично захваща скрола към границите на всяко изображение. onMomentumScrollEnd позволява актуализиране на индикатора на текущата страница. Такова карусело работи нативно и поддържа инерционно скролване.
За нестандартни стъпки на захващане се използва snapToInterval (размер на стъпката в пиксели) и snapToAlignment (start, center, end). Чрез snapToOffsets може да се зададе масив от конкретни позиции за захващане. Това е полезно за хоризонтални списъци с карти с различни размери.
Нека разгледаме два типични сценария: екран с формуляр (вертикално скролване) и хоризонтален списък с категории. И двата използват ScrollView с различни свойства за оптимално поведение.
Страницата за редактиране на профил съдържа разнородни елементи: аватар, няколко полета за въвеждане, превключватели и бутон за запис. ScrollView позволява скролване на цялата страница изцяло, а не всеки блок поотделно.
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>
);
Свойството keyboardShouldPersistTaps: 'handled' позволява скролване и взаимодействие с формуляра, когато клавиатурата е отворена. contentContainerStyle прилага разстояние до цялото съдържание. Този модел се използва във всички екрани с формуляри в React Native.
За навигация по категории (чатове, филтри, раздели) се използва хоризонтален ScrollView с чипове. Такъв компонент често се среща в приложения на пазари и социални мрежи.
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>
);
Хоризонтален ScrollView с изключен индикатор — стандарт за лентата с категории. Всеки чип е отделен компонент със състояние на избор. Свойството showsHorizontalScrollIndicator: false скрива лентата за скролване, което отговаря на очакванията на потребителите на мобилни приложения.
Често задавани въпроси
ScrollView е подходящ за малки количества данни (до 20-30 елемента) и разнородно съдържание (формуляри, профили, екрани с настройки). Изберете FlatList за дълги хомогенни списъци — новопоток, каталог на продукти, съобщения.
Използвайте събитие onScroll с onScrollEndDrag или onMomentumScrollEnd. В nativeEvent.contentOffset.y се съдържа текущата вертикална позиция. За производителност използвайте ScrollEventThrottle (iOS) за настройка на честотата на извикване на onScroll.
ScrollView рендерира всички елементи при монтиране, създавайки нативни графични елементи за всеки. При 50+ елемента на екрана натоварването на паметта и JS нишката се увеличава, причинявайки спад на кадрите. За такива случаи използвайте FlatList с мързеливо рендериране.
Задайте bounces={false}. Това свойство работи само на iOS и изключва пружиниращия ефект при достигане на ръба на ScrollView. На Android ефектът на отскачане не съществува по подразбиране, така че свойството се игнорира.
ScrollView не поддържа безкрайно скролване нативно. Въпреки това можете да комбинирате onScroll с проверка за приближаване до долния ръб (contentOffset.y + височина на екрана >= contentSize.height) и да добавяте елементи към state. За сериозни количества данни използвайте FlatList с onEndReached.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също