ScrollView
플랫폼의 ScrollView
를 감싸면서 터치 잠금 "응답자" 시스템과의 통합을 제공하는 컴포넌트다.
ScrollView
는 동작하기 위해 반드시 높이가 제한되어야 한다. 무한한 높이를 가진 자식 엘리먼트들을 제한된 높이의 컨테이너 안에 넣기 때문이다(스크롤 인터랙션을 통해). ScrollView
의 높이를 제한하려면, 뷰의 높이를 직접 설정하거나(비추천), 모든 부모 뷰가 제한된 높이를 가지도록 해야 한다. {flex: 1}
을 뷰 스택 아래로 전달하지 않으면 오류가 발생할 수 있으며, 엘리먼트 검사기를 통해 빠르게 디버깅할 수 있다.
아직은 다른 응답자가 이 스크롤 뷰가 응답자가 되는 것을 막는 경우를 지원하지 않는다.
<ScrollView>
vs <FlatList>
- 어떤 것을 사용해야 할까?
ScrollView
는 모든 자식 React 컴포넌트를 한 번에 렌더링하지만, 이는 성능 저하를 초래할 수 있다.
예를 들어, 매우 긴 목록을 표시해야 하고, 여러 화면 분량의 콘텐츠가 있다고 가정해보자. 모든 항목에 대해 JS 컴포넌트와 네이티브 뷰를 한 번에 생성하면, 보이지 않는 항목까지도 렌더링되어 느린 성능과 메모리 사용량 증가를 초래할 수 있다.
이때 FlatList
가 유용하다. FlatList
는 항목이 화면에 나타나기 직전에 렌더링하고, 화면에서 벗어난 항목은 제거하여 메모리와 처리 시간을 절약한다.
FlatList
는 또한 항목 사이에 구분선을 추가하거나, 여러 컬럼을 표시하거나, 무한 스크롤 로딩을 구현하는 등 다양한 기능을 기본적으로 지원한다.
참조
Props
View Props
View Props를 상속한다.
StickyHeaderComponent
스크롤 시 화면 상단에 고정되는 헤더를 렌더링하는 React 컴포넌트이다. stickyHeaderIndices
와 함께 사용해야 한다. 커스텀 트랜지션을 사용하는 스틱키 헤더가 필요한 경우, 예를 들어 리스트에 애니메이션이 적용되거나 숨겨지는 헤더를 구현할 때 이 컴포넌트를 설정해야 한다. 컴포넌트를 제공하지 않으면 기본적으로 ScrollViewStickyHeader
컴포넌트가 사용된다.
타입 |
---|
component, element |
alwaysBounceHorizontal
iOS
이 값을 true로 설정하면 스크롤 뷰의 콘텐츠가 스크롤 뷰 자체보다 작더라도 수평 방향으로 끝에 도달했을 때 바운스 효과가 발생한다.
타입 | 기본값 |
---|---|
bool | horizontal={true} 일 때 true 그 외의 경우 false |
alwaysBounceVertical
iOS
이 값을 true
로 설정하면, 스크롤 뷰의 콘텐츠가 스크롤 뷰 자체보다 작더라도 수직 방향으로 끝에 도달했을 때 바운스 효과가 발생한다.
타입 | 기본값 |
---|---|
bool | vertical={true} 일 때 false 그 외의 경우 true |
automaticallyAdjustContentInsets
iOS
네비게이션 바나 탭 바/툴바 뒤에 위치한 스크롤 뷰의 콘텐츠 여백을 iOS가 자동으로 조정할지 여부를 제어한다.
타입 | 기본값 |
---|---|
bool | true |
automaticallyAdjustKeyboardInsets
iOS
키보드 크기가 변경될 때 ScrollView가 contentInset
과 scrollViewInsets
을 자동으로 조정할지 여부를 제어한다.
타입 | 기본값 |
---|---|
bool | false |
automaticallyAdjustsScrollIndicatorInsets
iOS
iOS가 스크롤 인디케이터의 패딩을 자동으로 조정할지 여부를 제어한다. Apple의 해당 속성 문서를 참고한다.
타입 | 기본값 |
---|---|
bool | true |
bounces
iOS
이 값이 true
로 설정되면, 스크롤 방향 축에서 콘텐츠가 스크롤 뷰보다 큰 경우, 콘텐츠 끝에 도달했을 때 스크롤 뷰가 튕기는 효과가 발생한다. false
로 설정하면, alwaysBounce*
속성이 true
로 설정되어 있어도 모든 튕김 효과를 비활성화한다.
타입 | 기본값 |
---|---|
bool | true |
bouncesZoom
iOS
true
로 설정하면, 제스처로 인해 줌이 최소/최대 값을 넘어갈 수 있으며, 제스처가 끝날 때 줌이 최소/최대 값으로 애니메이션과 함께 돌아간다. false
로 설정하면 줌이 한계를 넘지 않는다.
타입 | 기본값 |
---|---|
bool | true |
canCancelContentTouches
iOS
이 값을 false
로 설정하면, 트래킹이 시작된 후 터치가 이동해도 드래그를 시도하지 않는다.
타입 | 기본값 |
---|---|
bool | true |
centerContent
iOS
true
로 설정하면, 콘텐츠가 스크롤 뷰의 경계보다 작을 때 자동으로 콘텐츠를 중앙에 배치한다. 콘텐츠가 스크롤 뷰보다 큰 경우, 이 속성은 아무런 영향을 미치지 않는다.
타입 | 기본값 |
---|---|
bool | false |
contentContainerStyle
이 스타일은 모든 자식 뷰를 감싸는 스크롤 뷰 컨텐츠 컨테이너에 적용된다. 예를 들면 다음과 같다:
return (
<ScrollView contentContainerStyle={styles.contentContainer}>
</ScrollView>
);
...
const styles = StyleSheet.create({
contentContainer: {
paddingVertical: 20
}
});
타입 |
---|
View Style |
contentInset
iOS
스크롤 뷰의 콘텐츠가 스크롤 뷰의 가장자리로부터 얼마나 안쪽으로 들어간지를 나타낸다.
타입 | 기본값 |
---|---|
객체: {top: number, left: number, bottom: number, right: number} | {top: 0, left: 0, bottom: 0, right: 0} |
contentInsetAdjustmentBehavior
iOS
이 속성은 스크롤 뷰의 콘텐츠 영역을 수정할 때 안전 영역 마진을 어떻게 사용할지 지정한다. iOS 11 이상에서 사용 가능하다.
타입 | 기본값 |
---|---|
enum('automatic' , 'scrollableAxes' , 'never' , 'always' ) | 'never' |
contentOffset
스크롤의 시작 위치를 수동으로 설정할 때 사용한다.
타입 | 기본값 |
---|---|
Point | {x: 0, y: 0} |
decelerationRate
사용자가 손가락을 뗀 후 스크롤 뷰가 얼마나 빠르게 감속하는지를 결정하는 부동소수점 숫자이다. 문자열 단축키 "normal"
과 "fast"
를 사용할 수도 있으며, 이는 각각 iOS의 UIScrollViewDecelerationRateNormal
과 UIScrollViewDecelerationRateFast
설정에 대응한다.
'normal'
: iOS에서는 0.998, Android에서는 0.985.'fast'
: iOS에서는 0.99, Android에서는 0.9.
타입 | 기본값 |
---|---|
enum('fast' , 'normal' ), number | 'normal' |
directionalLockEnabled
iOS
이 값을 true
로 설정하면, ScrollView는 드래그 중에 수직 또는 수평 스크롤 중 하나로만 고정하려고 시도한다.
타입 | 기본값 |
---|---|
bool | false |
disableIntervalMomentum
을 true
로 설정하면, 스크롤 뷰는 제스처의 속도와 상관없이 릴리스 시점의 스크롤 위치를 기준으로 다음 인덱스에서 멈춘다. 이 기능은 페이지의 너비가 가로 스크롤 뷰의 너비보다 작거나, 페이지의 높이가 세로 스크롤 뷰의 높이보다 작을 때 페이징에 유용하게 사용할 수 있다.
타입 | 기본값 |
---|---|
bool | false |
disableScrollViewPanResponder
이 값을 true로 설정하면 ScrollView의 기본 JS pan responder가 비활성화되고, ScrollView 내부의 터치 제어가 자식 컴포넌트에 완전히 위임된다. 이 옵션은 snapToInterval
이 활성화된 경우 특히 유용하다. snapToInterval
은 일반적인 터치 패턴을 따르지 않기 때문이다. snapToInterval
없이 일반적인 ScrollView 사용 사례에서는 이 옵션을 사용하지 않는 것이 좋다. 스크롤 중 예기치 않은 터치가 발생할 수 있다.
타입 | 기본값 |
---|---|
bool | false |
endFillColor
Android
스크롤뷰가 콘텐츠보다 더 많은 공간을 차지하는 경우가 있다. 이럴 때 이 프로퍼티를 사용하면 스크롤뷰의 남은 공간을 색상으로 채울 수 있다. 이렇게 하면 배경을 설정할 필요 없이 불필요한 오버드로를 방지할 수 있다. 일반적인 경우에는 필요하지 않은 고급 최적화 기법이다.
타입 |
---|
color |
fadingEdgeLength
Android
스크롤 콘텐츠의 가장자리를 흐리게 처리한다.
이 값이 0
보다 크면, 현재 스크롤 방향과 위치에 따라 가장자리가 흐려진다. 이를 통해 더 많은 콘텐츠가 있는지 여부를 표시한다.
타입 | 기본값 |
---|---|
number | 0 |
horizontal
이 true
로 설정되면, 스크롤 뷰의 자식 엘리먼트들이 세로가 아닌 가로로 배열된다.
타입 | 기본값 |
---|---|
bool | false |
indicatorStyle
iOS
스크롤 인디케이터의 스타일을 지정한다.
'default'
:black
과 동일하다.'black'
: 스크롤 인디케이터가 검정색이다. 밝은 배경에 적합하다.'white'
: 스크롤 인디케이터가 흰색이다. 어두운 배경에 적합하다.
타입 | 기본값 |
---|---|
enum('default' , 'black' , 'white' ) | 'default' |
invertStickyHeaders
스크롤 뷰에서 스틱키 헤더가 상단이 아닌 하단에 고정되도록 설정한다. 주로 뒤집힌 스크롤 뷰와 함께 사용한다.
타입 | 기본값 |
---|---|
bool | false |
keyboardDismissMode
드래그 동작에 따라 키보드가 사라지는 방식을 결정한다.
'none'
: 드래그해도 키보드가 사라지지 않는다.'on-drag'
: 드래그가 시작되면 키보드가 사라진다.
iOS 전용
'interactive'
: 드래그와 함께 키보드가 상호작용하며 사라지고, 터치와 동기화되어 움직인다. 위로 드래그하면 키보드 사라짐이 취소된다. Android에서는 이 기능을 지원하지 않으며,'none'
과 동일하게 동작한다.
타입 | 기본값 |
---|---|
enum('none' , 'on-drag' ) Android enum( 'none' , 'on-drag' , 'interactive' ) iOS | 'none' |
keyboardShouldPersistTaps
키보드가 탭 이후에도 계속 표시될지 여부를 결정한다.
'never'
: 키보드가 올라온 상태에서 포커스된 텍스트 입력 외부를 탭하면 키보드가 사라진다. 이 경우, 자식 컴포넌트는 탭 이벤트를 받지 못한다.'always'
: 키보드가 자동으로 사라지지 않으며, 스크롤 뷰가 탭을 잡아내지 않는다. 하지만 스크롤 뷰의 자식 컴포넌트가 탭을 잡아낼 수 있다.'handled'
: 스크롤 뷰의 자식 컴포넌트(또는 상위 컴포넌트)가 탭을 처리한 경우, 키보드가 자동으로 사라지지 않는다.false
: 더 이상 사용되지 않음,'never'
를 대신 사용한다.true
: 더 이상 사용되지 않음,'always'
를 대신 사용한다.
타입 | 기본값 |
---|---|
enum('always' , 'never' , 'handled' , false , true ) | 'never' |
maintainVisibleContentPosition
이 옵션을 설정하면 스크롤 뷰는 현재 보이는 첫 번째 자식 엘리먼트의 위치를 유지하도록 스크롤 위치를 조정한다. 이때 해당 엘리먼트는 minIndexForVisible
이상의 인덱스를 가져야 한다. 이 기능은 양방향으로 콘텐츠를 로드하는 리스트(예: 채팅 스레드)에서 유용하다. 새로운 메시지가 추가될 때 스크롤 위치가 튀는 현상을 방지할 수 있다. 일반적으로 값은 0으로 설정하지만, 로딩 스피너나 위치를 유지하지 않아야 할 콘텐츠를 건너뛰기 위해 1과 같은 다른 값을 사용할 수도 있다.
선택적으로 autoscrollToTopThreshold
를 설정하면, 사용자가 조정 전에 상단 임계값 이내에 있었다면 콘텐츠를 자동으로 상단으로 스크롤할 수 있다. 이는 채팅과 같은 애플리케이션에서 새 메시지가 자연스럽게 표시되도록 할 때 유용하다. 단, 사용자가 이미 상단에서 멀리 스크롤한 경우에는 스크롤이 방해가 될 수 있으므로 주의가 필요하다.
주의사항 1: 이 기능을 활성화한 상태에서 스크롤 뷰 내부의 엘리먼트 순서를 재정렬하면 스크롤이 튀거나 끊기는 현상이 발생할 수 있다. 이 문제는 해결 가능하지만, 현재는 개선할 계획이 없다. 따라서 이 기능을 사용하는 모든 ScrollView
또는 List
의 콘텐츠 순서를 변경하지 않는 것이 좋다.
주의사항 2: 이 기능은 네이티브 코드에서 contentOffset
과 frame.origin
을 사용해 콘텐츠의 가시성을 계산한다. 따라서 오클루전, 변환 등과 같은 복잡한 요소는 "보이는지 여부"를 판단할 때 고려되지 않는다.
타입 |
---|
object: {minIndexForVisible: number, autoscrollToTopThreshold: number} |
maximumZoomScale
iOS
허용되는 최대 확대 비율이다.
타입 | 기본값 |
---|---|
number | 1.0 |
minimumZoomScale
iOS
허용되는 최소 줌 배율.
타입 | 기본값 |
---|---|
number | 1.0 |
nestedScrollEnabled
Android
Android API 레벨 21 이상에서 중첩 스크롤을 활성화한다.
타입 | 기본값 |
---|---|
bool | false |
onContentSizeChange
ScrollView의 스크롤 가능한 콘텐츠 뷰가 변경될 때 호출된다.
핸들러 함수는 콘텐츠의 너비와 높이 (contentWidth, contentHeight)
를 두 개의 인자로 받는다.
이 기능은 ScrollView가 렌더링하는 콘텐츠 컨테이너에 부착된 onLayout 핸들러를 통해 구현된다.
타입 |
---|
function |
onMomentumScrollBegin
스크롤 뷰가 미끄러지기 시작할 때 발생하는 모멘텀 스크롤이 시작될 때 호출된다.
타입 |
---|
function |
onMomentumScrollEnd
스크롤뷰가 미끄러지듯 멈출 때 발생하는 모멘텀 스크롤이 끝나면 호출된다.
타입 |
---|
function |
onScroll
스크롤 중에 최대 프레임당 한 번씩 발생한다. 이벤트는 다음과 같은 구조를 가진다(모든 값은 숫자 타입이다):
{
nativeEvent: {
contentInset: {bottom, left, right, top},
contentOffset: {x, y},
contentSize: {height, width},
layoutMeasurement: {height, width},
zoomScale
}
}
타입 |
---|
function |
onScrollBeginDrag
사용자가 스크롤 뷰를 드래그하기 시작할 때 호출된다.
타입 |
---|
function |
onScrollEndDrag
사용자가 스크롤 뷰 드래그를 멈추고, 스크롤이 완전히 정지하거나 미끄러지기 시작할 때 호출된다.
타입 |
---|
function |
onScrollToTop
iOS
스크롤 뷰가 상단으로 스크롤될 때 발생한다. 주로 상태 표시줄을 탭한 후에 이 이벤트가 실행된다.
타입 |
---|
function |
overScrollMode
Android
오버스크롤 모드의 기본값을 재정의할 때 사용한다.
가능한 값:
'auto'
- 콘텐츠가 충분히 크고 의미 있는 스크롤이 가능한 경우에만 오버스크롤을 허용한다.'always'
- 항상 오버스크롤을 허용한다.'never'
- 오버스크롤을 허용하지 않는다.
타입 | 기본값 |
---|---|
enum('auto' , 'always' , 'never' ) | 'auto' |
pagingEnabled
이 값을 true
로 설정하면 스크롤 뷰가 스크롤할 때 스크롤 뷰의 크기 배수 위치에서 멈춘다. 이 기능은 가로 방향 페이지네이션을 구현할 때 사용할 수 있다.
타입 | 기본값 |
---|---|
bool | false |
persistentScrollbar
Android
스크롤바가 사용되지 않을 때 투명해지지 않도록 설정한다.
타입 | 기본값 |
---|---|
bool | false |
pinchGestureEnabled
iOS
이 값을 true로 설정하면 ScrollView에서 핀치 제스처를 사용해 확대 및 축소할 수 있다.
타입 | 기본값 |
---|---|
bool | true |
refreshControl
refreshControl
은 ScrollView
에 당겨서 새로고침(pull-to-refresh) 기능을 제공하는 컴포넌트다. 이 기능은 세로 방향의 ScrollView
에서만 동작하며, horizontal
속성을 false
로 설정해야 한다.
자세한 내용은 RefreshControl 문서를 참고한다.
타입 |
---|
엘리먼트 |
removeClippedSubviews
실험적 기능: true
로 설정하면, 화면 밖에 있는 자식 뷰들( overflow
값이 hidden
인 경우)이 네이티브 상위 뷰에서 제거된다. 이 기능은 긴 목록에서 스크롤 성능을 향상시킬 수 있다.
타입 | 기본값 |
---|---|
bool | false |
scrollEnabled
이 값을 false로 설정하면 터치 인터랙션을 통해 뷰를 스크롤할 수 없다.
단, scrollTo
를 호출하면 언제든지 뷰를 스크롤할 수 있다.
타입 | 기본값 |
---|---|
bool | true |
scrollEventThrottle
스크롤 이벤트가 발생하는 빈도를 제한하며, 시간 간격(ms)으로 지정한다. 스크롤에 반응해 비용이 많이 드는 작업을 수행할 때 유용하다. 값이 16
이하인 경우, 디바이스의 새로 고침 빈도와 상관없이 스로틀링이 비활성화된다.
타입 | 기본값 |
---|---|
number | 0 |
scrollIndicatorInsets
iOS
스크롤 뷰의 표시기(인디케이터)가 스크롤 뷰의 가장자리에서 얼마나 안쪽으로 들어갈지를 설정한다. 일반적으로 contentInset
과 동일한 값으로 설정한다.
타입 | 기본값 |
---|---|
객체: {top: number, left: number, bottom: number, right: number} | {top: 0, left: 0, bottom: 0, right: 0} |
scrollPerfTag
Android
스크롤 성능을 기록하기 위해 사용되는 태그다. 이 태그는 모멘텀 이벤트를 강제로 활성화한다(자세한 내용은 sendMomentumEvents 참조). 기본적으로는 아무런 동작을 하지 않으며, 이를 활용하려면 커스텀 네이티브 FpsListener를 구현해야 한다.
타입 |
---|
string |
scrollToOverflowEnabled
iOS
이 값이 true
로 설정되면, 스크롤 뷰는 프로그래밍 방식으로 콘텐츠 크기를 넘어서 스크롤할 수 있다.
타입 | 기본값 |
---|---|
bool | false |
scrollsToTop
iOS
true
로 설정하면, 상태 바를 탭할 때 스크롤 뷰가 상단으로 스크롤된다.
타입 | 기본값 |
---|---|
bool | true |
showsHorizontalScrollIndicator
이 값을 true
로 설정하면 수평 스크롤 표시기가 나타난다.
타입 | 기본값 |
---|---|
bool | true |
showsVerticalScrollIndicator
true
로 설정하면 세로 스크롤 표시기를 보여준다.
타입 | 기본값 |
---|---|
bool | true |
snapToAlignment
iOS
snapToInterval
이 설정된 경우, snapToAlignment
는 스크롤 뷰에서 스냅핑의 위치를 정의한다.
가능한 값:
'start'
는 스냅을 왼쪽(가로) 또는 상단(세로)에 정렬한다.'center'
는 스냅을 중앙에 정렬한다.'end'
는 스냅을 오른쪽(가로) 또는 하단(세로)에 정렬한다.
타입 | 기본값 |
---|---|
enum('start' , 'center' , 'end' ) | 'start' |
snapToEnd
snapToOffsets
와 함께 사용한다. 기본적으로 리스트의 끝은 스냅 오프셋으로 간주된다. snapToEnd
를 false로 설정하면 이 동작을 비활성화하고 리스트가 끝과 마지막 snapToOffsets
오프셋 사이에서 자유롭게 스크롤되도록 한다.
타입 | 기본값 |
---|---|
bool | true |
snapToInterval
이 값을 설정하면 스크롤 뷰가 snapToInterval
값의 배수 위치에서 멈춘다. 이 기능은 스크롤 뷰보다 길이가 작은 자식 요소들을 페이지 단위로 넘길 때 유용하다. 일반적으로 snapToAlignment
와 decelerationRate="fast"
와 함께 사용한다. 이 설정은 덜 유연한 pagingEnabled
속성을 대체한다.
타입 |
---|
number |
snapToOffsets
이 속성을 설정하면 스크롤 뷰가 정의된 오프셋 위치에서 멈춘다. 스크롤 뷰보다 작은 크기의 다양한 자식 요소를 페이지 단위로 넘길 때 유용하다. 일반적으로 decelerationRate="fast"
와 함께 사용한다. 이 속성은 더 제한적인 설정을 가진 pagingEnabled
와 snapToInterval
속성을 덮어쓴다.
타입 |
---|
숫자 배열 |
snapToStart
snapToOffsets
와 함께 사용한다. 기본적으로 리스트의 시작 부분이 스냅 오프셋으로 간주된다. snapToStart
를 false
로 설정하면 이 동작을 비활성화하고, 리스트의 시작 부분과 첫 번째 snapToOffsets
오프셋 사이에서 자유롭게 스크롤할 수 있다.
타입 | 기본값 |
---|---|
bool | true |
stickyHeaderHiddenOnScroll
이 값을 true
로 설정하면 리스트를 아래로 스크롤할 때 스틱키 헤더가 숨겨진다. 그리고 위로 스크롤할 때 리스트 상단에 고정된다.
타입 | 기본값 |
---|---|
bool | false |
stickyHeaderIndices
스크롤할 때 화면 상단에 고정될 자식 요소들의 인덱스를 지정하는 배열이다. 예를 들어, stickyHeaderIndices={[0]}
을 전달하면 첫 번째 자식 요소가 스크롤 뷰의 상단에 고정된다. 여러 요소를 상단에 고정하려면 [x,y,z]
와 같은 형태로 여러 인덱스를 지정할 수 있다. 이 속성은 horizontal={true}
와 함께 사용할 수 없다.
타입 |
---|
숫자 배열 |
zoomScale
iOS
스크롤 뷰 콘텐츠의 현재 확대/축소 비율을 나타낸다.
타입 | 기본값 |
---|---|
number | 1.0 |
메서드
flashScrollIndicators()
flashScrollIndicators();
스크롤 인디케이터를 잠시 동안 표시한다.
scrollTo()
scrollTo(
options?: {x?: number, y?: number, animated?: boolean} | number,
deprecatedX?: number,
deprecatedAnimated?: boolean,
);
특정 x, y 좌표로 즉시 이동하거나 부드러운 애니메이션과 함께 스크롤한다.
예제:
scrollTo({x: 0, y: 0, animated: true})
참고: 이 함수의 독특한 시그니처는 역사적인 이유로 인해 옵션 객체 대신 개별 인자를 받을 수 있도록 설계된 것이다. 이 방식은 모호성(y가 x보다 먼저 오는 문제) 때문에 더 이상 사용하지 않는 것이 좋다.
scrollToEnd()
scrollToEnd(options?: {animated?: boolean});
이 메서드는 수직 ScrollView인 경우 맨 아래로 스크롤한다. 수평 ScrollView인 경우 오른쪽 끝으로 스크롤한다.
부드러운 애니메이션 효과를 원한다면 scrollToEnd({animated: true})
를 사용하고, 즉각적인 스크롤을 원한다면 scrollToEnd({animated: false})
를 사용한다. 옵션을 전달하지 않으면 animated
는 기본값인 true
로 설정된다.