ScrollView
Component that wraps platform ScrollView while providing integration with touch locking "responder" system.
Keep in mind that ScrollViews must have a bounded height in order to work, since they contain unbounded-height children into a bounded container (via a scroll interaction). In order to bound the height of a ScrollView, either set the height of the view directly (discouraged) or make sure all parent views have bounded height. Forgetting to transfer {flex: 1}
down the view stack can lead to errors here, which the element inspector makes quick to debug.
Doesn't yet support other contained responders from blocking this scroll view from becoming the responder.
<ScrollView>
vs <FlatList>
- which one to use?
ScrollView
renders all its react child components at once, but this has a performance downside.
Imagine you have a very long list of items you want to display, maybe several screens worth of content. Creating JS components and native views for everything all at once, much of which may not even be shown, will contribute to slow rendering and increased memory usage.
This is where FlatList
comes into play. FlatList
renders items lazily, when they are about to appear, and removes items that scroll way off screen to save memory and processing time.
FlatList
is also handy if you want to render separators between your items, multiple columns, infinite scroll loading, or any number of other features it supports out of the box.
Example
import React from 'react';
import {
StyleSheet,
Text,
SafeAreaView,
ScrollView,
StatusBar,
} from 'react-native';
const App = () => {
return (
<SafeAreaView style={styles.container}>
<ScrollView style={styles.scrollView}>
<Text style={styles.text}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
</Text>
</ScrollView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: StatusBar.currentHeight,
},
scrollView: {
backgroundColor: 'pink',
marginHorizontal: 20,
},
text: {
fontSize: 42,
},
});
export default App;
Reference
Props
View Props
Inherits View Props.
bounces
When true, the scroll view bounces when it reaches the end of the content if the content is larger than the scroll view along the axis of the scroll direction. When false
, it disables all bouncing even if the alwaysBounce*
props are true
.
Type | Default |
---|---|
bool | true |
contentOffset
Used to manually set the starting scroll offset.
Type | Default |
---|---|
Point | {x: 0, y: 0} |
decelerationRate
A floating-point number that determines how quickly the scroll view decelerates after the user lifts their finger. You may also use string shortcuts "normal"
and "fast"
which match the underlying settings for UIScrollViewDecelerationRateNormal
and UIScrollViewDecelerationRateFast
respectively.
'normal'
0.998'fast'
, 0.9
Type | Default |
---|---|
enum('fast' , 'normal' ), number |
'normal' |
horizontal
When true
, the scroll view's children are arranged horizontally in a row instead of vertically in a column.
Type | Default |
---|---|
bool | false |
maintainVisibleContentPosition
When set, the scroll view will adjust the scroll position so that the first child that is currently visible and at or beyond minIndexForVisible
will not change position. This is useful for lists that are loading content in both directions, e.g. a chat thread, where new messages coming in might otherwise cause the scroll position to jump. A value of 0 is common, but other values such as 1 can be used to skip loading spinners or other content that should not maintain position.
The optional autoscrollToTopThreshold
can be used to make the content automatically scroll to the top after making the adjustment if the user was within the threshold of the top before the adjustment was made. This is also useful for chat-like applications where you want to see new messages scroll into place, but not if the user has scrolled up a ways and it would be disruptive to scroll a bunch.
Caveat 1: Reordering elements in the scrollview with this enabled will probably cause jumpiness and jank. It can be fixed, but there are currently no plans to do so. For now, don't re-order the content of any ScrollViews or Lists that use this feature.
Caveat 2: This uses contentOffset
and frame.origin
in native code to compute visibility. Occlusion, transforms, and other complexity won't be taken into account as to whether content is "visible" or not.
Type |
---|
object: {minIndexForVisible: number, autoscrollToTopThreshold: number} |
Note: On Kepler, the view flattening optimization can impact the indices of the ScrollView's children in the underlying native code implementation of the view. This can result in unexpected behavior when specifying minIndexForVisible
. To ensure that indices are preserved, collapsable: false
should be passed to the direct children of the ScrollView.
scrollSlop - Kepler Only
Optional parameter to set the distance (in pixels) to drag before the scrollview starts scrolling.
Type |
---|
number |
onScroll
Fires at most once per frame during scrolling. The event has the following shape (all values are numbers):
{
nativeEvent: {
contentInset: {bottom, left, right, top},
contentOffset: {x, y},
contentSize: {height, width},
layoutMeasurement: {height, width},
zoomScale
}
}
Type |
---|
function |
onScrollBeginDrag
Called when the user begins to drag the scroll view.
Type |
---|
function |
onScrollEndDrag
Called when the user stops dragging the scroll view and it either stops or begins to glide.
Type |
---|
function |
removeClippedSubviews
Experimental: When true
, offscreen child views (whose overflow
value is hidden
) are removed from their native backing superview when offscreen. This can improve scrolling performance on long lists.
Type | Default |
---|---|
bool | false |
scrollEnabled
When false, the view cannot be scrolled via touch interaction or D-Pad navigation. On TV devices, key-based interactions (such as using a remote) for navigation are also disabled.
You can scroll the view by calling scrollTo
. Set this prop to false
when the app requires full control over both scrolling behavior and focus management, particularly in custom navigation scenarios to avoid dual scrolling.
focusable
prop to the same value. In other words, explicitly setting the focusable
prop has no effect if scrollEnabled
is also set.Type | Default |
---|---|
bool | true |
scrollEventThrottle
Limits how often scroll events will be fired while scrolling, specified as a time interval in ms. This may be useful when expensive work is performed in response to scrolling. Values ≤ 16 will disable throttling, regardless of the refresh rate of the device.
Type | Default |
---|---|
number | 0 |
onContentSizeChange
Called when the dimensions of a ScrollView's content has changed.
The callback function receives two parameters: the content width and content height (contentWidth, contentHeight)
.
Type |
---|
function |
pagingEnabled
When true, the scroll view stops on multiples of the scroll view's size when scrolling. This can be used for horizontal pagination.
Type | Default |
---|---|
bool | false |
persistentScrollbar
Disables scrollbar transparency when the scrollbar isn't in use.
Note: Don't use this property in conjunction with showsVerticalScrollIndicator
or showsHorizontalScrollIndicator
. Scrollbar visibility is triggered only upon scroll event initiation.
Type | Default |
---|---|
bool | false |
showsHorizontalScrollIndicator
When true
, shows a horizontal scroll indicator.
Type | Default |
---|---|
bool | false |
showsVerticalScrollIndicator
When true
, shows a vertical scroll indicator.
Type | Default |
---|---|
bool | false |
snapToAlignment
When snapToInterval
is set, snapToAlignment
will define the relationship of the snapping to the scroll view.
Possible values:
'start'
will align the snap at the left (horizontal) or top (vertical).'center'
will align the snap in the center.'end'
will align the snap at the right (horizontal) or bottom (vertical).
Type | Default |
---|---|
enum('start' , 'center' , 'end' ) |
'start' |
snapToEnd
Use in conjunction with snapToOffsets
. By default, the end of the list counts as a snap offset. Set snapToEnd
to false to disable this behavior and allow the list to scroll freely between its end and the last snapToOffsets
offset.
Type | Default |
---|---|
bool | true |
snapToInterval
When set, causes the scroll view to stop at multiples of the value of snapToInterval
. This can be used for paginating through children that have lengths smaller than the scroll view. Typically used in combination with snapToAlignment
and decelerationRate="fast"
. Overrides less configurable pagingEnabled
prop.
Type |
---|
number |
snapToOffsets
When set, causes the scroll view to stop at the defined offsets. This can be used for paginating through variously sized children that have lengths smaller than the scroll view. Typically used in combination with decelerationRate="fast"
. Overrides less configurable pagingEnabled
and snapToInterval
props.
Type |
---|
array of number |
snapToStart
Use in conjunction with snapToOffsets
. By default, the beginning of the list counts as a snap offset. Set snapToStart
to false
to disable this behavior and allow the list to scroll freely between its start and the first snapToOffsets
offset.
Type | Default |
---|---|
bool | true |
stickyHeaderHiddenOnScroll
When set to true
, sticky header will be hidden when scrolling down the list, and it will dock at the top of the list when scrolling up.
Type | Default |
---|---|
bool | false |
stickyHeaderIndices
An array of child indices determining which children get docked to the top of the screen when scrolling. For example, passing stickyHeaderIndices={[0]}
will cause the first child to be fixed to the top of the scroll view. You can also use like [x,y,z] to make multiple items sticky when they are at the top. This property is not supported in conjunction with horizontal={true}
.
Type |
---|
array of number |
Methods
flashScrollIndicators()
flashScrollIndicators();
Displays the scroll indicators momentarily.
scrollTo()
scrollTo(
options?: {x?: number, y?: number, animated?: boolean} | number,
deprecatedX?: number,
deprecatedAnimated?: boolean,
);
Scrolls to a given x, y offset, either immediately, with a smooth animation.
animated
defaults to true
. false
is not supported.
Example:
scrollTo({x: 0, y: 0, animated: true})
Note: The weird function signature is due to the fact that, for historical reasons, the function also accepts separate arguments as an alternative to the options object. This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
animated
defaults to true
. false
is not supported.
scrollToEnd()
scrollToEnd(options?: {animated?: boolean});
If this is a vertical ScrollView scrolls to the bottom. If this is a horizontal ScrollView scrolls to the right.
animated
defaults to true
. false
is not supported.
Known issues
hasTVPreferredFocus
(inherited from View Props) is not supported on Kepler, setting it totrue
can result in undefined behavior.
Last updated: Sep 30, 2025