Komponent ScrollView w React Native — kontener z możliwością przewijania zawartości, która przekracza rozmiary ekranu. W przeciwieństwie do FlatList, ScrollView renderuje całą zawartość od razu, co jest optymalne dla małych ilości danych, formularzy i ekranów o znanej wysokości. Według React Native Docs, 2024, ScrollView obsługuje przewijanie pionowe i poziome, zdarzenie onScroll, programowe sterowanie pozycją oraz gesty zoomu. Komponent renderuje się w natywny UIScrollView na iOS i ScrollView na Androidzie.
Najważniejsze
ScrollView — to komponent React Native, który owija swoją zawartość w kontener z możliwością przewijania. Jeśli zawartość wykracza poza granice ekranu, użytkownik może przewijać ją pionowo lub poziomo. ScrollView renderuje wszystkie elementy podrzędne podczas montowania, niezależnie od tego, czy są widoczne na ekranie, czy nie.
W przeciwieństwie do FlatList, który renderuje tylko widoczne elementy (lazy rendering), ScrollView tworzy wszystkie natywne reprezentacje od razu. To sprawia, że ScrollView jest wygodny dla formularzy, stron ustawień, kart produktów na jednym ekranie — wszędzie tam, gdzie liczba elementów podrzędnych jest niewielka (do 20-30) lub ich dokładna liczba nie jest z góry znana.
Według React Native Using ScrollView, 2024, ScrollView obsługuje zagnieżdżone przewijanie (np. ScrollView wewnątrz ScrollView), efekt odbicia przy osiągnięciu krawędzi, wskaźniki przewijania, blokowanie pozycji (snap) i obsługę gestów. Na iOS ScrollView automatycznie dodaje odstęp pod SafeArea przez contentInsetAdjustmentBehavior.
ScrollView udostępnia bogaty zestaw właściwości do sterowania zachowaniem przewijania, wyglądem i interaktywnością. Rozważmy kluczowe grupy: sterowanie przewijaniem, ustawienia wizualne, zdarzenia i cechy platformy.
horizontal — przełącza kierunek przewijania z pionowego (domyślnie) na poziomy. scrollEnabled — wyłącza przewijanie w razie potrzeby. showsVerticalScrollIndicator i showsHorizontalScrollIndicator sterują wyświetlaniem wskaźników przewijania. bounces (iOS) włącza/wyłącza efekt odbicia przy osiągnięciu krawędzi zawartości.
Główne zdarzenie — onScroll, wywoływane przy każdym przewinięciu i przekazujące obiekt z nativeEvent, zawierający contentOffset (bieżąca pozycja), contentSize (rozmiar zawartości), layoutMeasurement (rozmiar widocznego obszaru). onMomentumScrollEnd wywoływane po zakończeniu przewijania bezwładnościowego. onScrollEndDrag — gdy użytkownik puścił ekran. Te zdarzenia są używane do implementacji nieskończonego przewijania, paralaksy i leniwego ładowania.
ScrollView udostępnia metody do programowego sterowania przez referencję: scrollTo({x, y, animated}) przewija do wskazanych współrzędnych, scrollToEnd({animated}) — na koniec zawartości, flashScrollIndicators() — tymczasowo pokazuje wskaźniki przewijania.
const scrollRef = useRef(null);
// Przewiń do góry
scrollRef.current.scrollTo({ x: 0, y: 0, animated: true });
// Przewiń do końca
scrollRef.current.scrollToEnd({ animated: true });
Programowe sterowanie przewijaniem jest często używane w czatach (autoprzewijanie do ostatniej wiadomości), formularzach (przewijanie do pola z błędem) i karuzelach (programowe przewijanie).
Wybór między ScrollView a FlatList — jedno z kluczowych decyzji architektonicznych w React Native. Oba komponenty zapewniają przewijanie, ale stosują zasadniczo różne strategie renderowania. ScrollView renderuje wszystko od razu, FlatList — tylko widoczne elementy.
| Cecha | ScrollView | FlatList |
|---|---|---|
| Renderowanie | Wszystkie elementy od razu | Tylko widoczne + buffer |
| Wydajność | Spada przy 30+ elementach | Stabilna przy dowolnej ilości |
| Zawartość | Dowolne komponenty (formularze, karty) | Jednorodne elementy z tablicy |
| Rozmiar danych | Mały i średni (do 30 elementów) | Duży i nieograniczony |
| Poziomy scroll | Tak (właściwość horizontal) | Tak (horizontal) |
| Sekcje | Nie (renderuje jak jest) | SectionList dla sekcji |
Zasada wyboru: ScrollView — dla ekranów, gdzie liczba elementów podrzędnych jest znana i nie przekracza 20-30 (profil użytkownika, formularz ustawień, strona produktu). FlatList — dla list z potencjalnie dużą liczbą elementów (kanał newsów, katalog produktów, wiadomości czatu). Jeśli zawartość jest różnorodna (nagłówek, formularz, karta, stopka) — ScrollView jest lepszy, ponieważ FlatList oczekuje jednorodnych elementów.
ScrollView obsługuje przewijanie poziome przez właściwość horizontal, co czyni go idealnym dla karuzel, galerii obrazów, zakładek i poziomych list. W połączeniu z właściwością pagingEnabled (iOS) lub snapToInterval ScrollView staje się komponentem do nawigacji stronicowej.
Właściwość horizontal przełącza kierunek przewijania. pagingEnabled (iOS) włącza przewijanie stronicowe, przy którym scroll zatrzymuje się tylko na granicach elementów. snapToInterval ustawia krok przyciągania w pikselach dla obu platform.
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>
);
W tej karuzeli pagingEnabled automatycznie przyciąga scroll do granic każdego obrazu. onMomentumScrollEnd pozwala aktualizować wskaźnik bieżącej strony. Taka karuzela działa natywnie i obsługuje przewijanie bezwładnościowe.
Dla niestandardowych kroków przyciągania używa się snapToInterval (rozmiar kroku w pikselach) i snapToAlignment (start, center, end). Za pomocą snapToOffsets można ustawić tablicę konkretnych pozycji do przyciągania. Jest to przydatne dla poziomych list z kartami o różnym rozmiarze.
Rozważmy dwa typowe scenariusze: ekran z formularzem (przewijanie pionowe) i poziomą listę kategorii. Oba używają ScrollView z różnymi właściwościami dla optymalnego zachowania.
Strona edycji profilu zawiera różnorodne elementy: awatar, kilka pól wprowadzania, przełączniki i przycisk zapisu. ScrollView pozwala przewijać całą stronę w całości, a nie każdy blok osobno.
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>
);
Właściwość keyboardShouldPersistTaps: 'handled' pozwala przewijać i wchodzić w interakcje z formularzem, gdy klawiatura jest otwarta. contentContainerStyle stosuje odstępy do całej zawartości. Ten wzorzec jest używany we wszystkich ekranach z formularzami w React Native.
Do nawigacji po kategoriach (czaty, filtry, zakładki) używa się poziomego ScrollView z chipami. Taki komponent często występuje w aplikacjach marketplace'ów i sieci społecznościowych.
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>
);
Poziomy ScrollView z wyłączonym wskaźnikiem — standard dla paska kategorii. Każdy chip to osobny komponent z stanem zaznaczenia. Właściwość showsHorizontalScrollIndicator: false usuwa pasek przewijania, co odpowiada oczekiwaniom użytkowników aplikacji mobilnych.
Często zadawane pytania
ScrollView nadaje się do małych ilości danych (do 20-30 elementów) i różnorodnej zawartości (formularze, profile, ekrany ustawień). FlatList wybierz dla długich jednorodnych list — kanał newsów, katalog produktów, wiadomości.
Użyj zdarzenia onScroll z onScrollEndDrag lub onMomentumScrollEnd. W nativeEvent.contentOffset.y zawarta jest bieżąca pozycja pionowa. Dla wydajności użyj ScrollEventThrottle (iOS) do ustawienia częstotliwości wywołania onScroll.
ScrollView renderuje wszystkie elementy podczas montowania, tworząc natywne reprezentacje dla każdego. Przy 50+ elementach na ekranie obciążenie pamięci i wątku JS rośnie, powodując spadki klatek. W takich przypadkach użyj FlatList z leniwym renderowaniem.
Ustaw bounces={false}. Ta właściwość działa tylko na iOS i wyłącza efekt sprężystości przy osiągnięciu krawędzi ScrollView. Na Androidzie efekt odbicia nie występuje domyślnie, więc właściwość jest ignorowana.
ScrollView nie obsługuje nieskończonego przewijania natywnie. Można jednak połączyć onScroll ze sprawdzeniem zbliżania się do dolnej krawędzi (contentOffset.y + wysokość ekranu >= contentSize.height) i dodawać elementy do stanu. Dla poważnych ilości danych używaj FlatList z onEndReached.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również