ScrollView
플랫폼의 ScrollView를 감싸면서 터치 잠금 "응답자" 시스템과의 통합을 제공하는 컴포넌트다.
ScrollView는 반드시 높이가 제한되어야 한다. 무제한 높이의 자식 요소를 스크롤 상호작용을 통해 제한된 컨테이너에 담기 때문이다. ScrollView의 높이를 제한하려면 직접 뷰의 높이를 설정하거나(비추천), 모든 부모 뷰의 높이가 제한되어 있는지 확인해야 한다. {flex: 1}
을 뷰 스택 아래로 전달하지 않으면 오류가 발생할 수 있으며, 엘리먼트 검사기를 통해 빠르게 디버깅할 수 있다.
아직은 다른 응답자가 이 ScrollView가 응답자가 되는 것을 막는 경우를 지원하지 않는다.
<ScrollView>
vs <FlatList>
- 어떤 것을 사용할까?
ScrollView
는 모든 자식 React 컴포넌트를 한 번에 렌더링한다. 하지만 이는 성능상의 단점이 있다.
예를 들어, 여러 화면에 걸친 긴 목록을 표시하려 한다고 가정해보자. 모든 항목에 대한 JS 컴포넌트와 네이티브 뷰를 한 번에 생성하면, 보이지도 않는 많은 항목들이 느린 렌더링과 메모리 사용량 증가를 초래할 수 있다.
이때 FlatList
가 유용하다. FlatList
는 항목이 화면에 나타나기 직전에 지연 렌더링하고, 화면에서 벗어난 항목은 제거하여 메모리와 처리 시간을 절약한다.
FlatList
는 또한 항목 사이에 구분선을 렌더링하거나, 여러 컬럼을 표시하거나, 무한 스크롤 로딩을 구현하는 등 다양한 기능을 기본적으로 지원한다.
예제
참고 자료
Props
View Props
View Props를 상속받는다.
StickyHeaderComponent
스크롤 시 스틱키 고정 헤더를 렌더링하는 리액트 컴포넌트다. 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
스틱키 헤더가 ScrollView의 상단이 아닌 하단에 고정되도록 설정한다. 주로 반전된 ScrollView와 함께 사용한다.
타입 | 기본값 |
---|---|
bool | false |
keyboardDismissMode
드래그 동작에 따라 키보드가 사라지는 방식을 결정한다.
'none'
: 드래그해도 키보드가 사라지지 않는다.'on-drag'
: 드래그를 시작하면 키보드가 사라진다.
iOS 전용
'interactive'
: 드래그와 함께 키보드가 상호작용적으로 사라지며, 터치 위치에 맞춰 움직인다. 위로 드래그하면 키보드 사라짐이 취소된다. 안드로이드에서는 이 기능을 지원하지 않으며,'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: 이 기능을 활성화한 상태에서 스크롤 뷰 내 엘리먼트의 순서를 변경하면 스크롤이 튀거나 불안정해질 수 있다. 이 문제는 해결 가능하지만, 현재는 수정할 계획이 없다. 따라서 이 기능을 사용하는 모든 스크롤 뷰나 리스트의 콘텐츠 순서를 변경하지 말아야 한다.
주의사항 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
pagingEnabled
를 true로 설정하면, 스크롤 뷰가 스크롤할 때 스크롤 뷰의 크기 배수에서 멈춘다. 이 기능은 가로 방향 페이징에 활용할 수 있다.
타입 | 기본값 |
---|---|
bool | false |
persistentScrollbar
Android
스크롤바가 사용되지 않을 때 투명해지지 않도록 설정한다.
타입 | 기본값 |
---|---|
bool | false |
pinchGestureEnabled
iOS
이 값을 true로 설정하면 ScrollView에서 핀치 제스처를 사용하여 확대/축소할 수 있다.
타입 | 기본값 |
---|---|
bool | true |
refreshControl
ScrollView에 pull-to-refresh 기능을 제공하는 RefreshControl 컴포넌트다. 이 기능은 세로 방향의 ScrollView에서만 동작한다 (horizontal
prop은 반드시 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
로 설정된다.