스크롤 수정자
verticalScroll 및 horizontalScroll 수정자는 콘텐츠의 경계가 최대 크기 제약 조건보다 클 때 사용자가 요소를 스크롤할 수 있는 가장 간단한 방법을 제공합니다. verticalScroll 및 horizontalScroll 수정자를 사용하면 콘텐츠를 변환하거나 오프셋할 필요가 없습니다.
@Composable private fun ScrollBoxes() { Column( modifier = Modifier .background(Color.LightGray) .size(100.dp) .verticalScroll(rememberScrollState()) ) { repeat(10) { Text("Item $it", modifier = Modifier.padding(2.dp)) } } }

ScrollState를 사용하면 스크롤 위치를 변경하거나 현재 상태를 가져올 수 있습니다. 기본 매개변수를 사용하여 만들려면 rememberScrollState()를 사용하세요.
@Composable private fun ScrollBoxesSmooth() { // Smoothly scroll 100px on first composition val state = rememberScrollState() LaunchedEffect(Unit) { state.animateScrollTo(100) } Column( modifier = Modifier .background(Color.LightGray) .size(100.dp) .padding(horizontal = 8.dp) .verticalScroll(state) ) { repeat(10) { Text("Item $it", modifier = Modifier.padding(2.dp)) } } }
스크롤 가능한 영역 수정자
scrollableArea 수정자는 맞춤 스크롤 가능한 컨테이너를 만들기 위한 기본 구성요소입니다. scrollable 수정자에 대한 상위 수준 추상화를 제공하여 동작 델타 해석, 콘텐츠 클리핑, 오버스크롤 효과와 같은 일반적인 요구사항을 처리합니다.
scrollableArea는 맞춤 구현에 사용되지만 일반적으로 표준 스크롤 목록에는 verticalScroll, horizontalScroll과 같은 기성 솔루션이나 LazyColumn과 같은 컴포저블을 사용하는 것이 좋습니다. 이러한 상위 수준 구성요소는 일반적인 사용 사례에 더 간단하며 scrollableArea를 사용하여 빌드됩니다.
scrollableArea 및 scrollable 수정자 간의 차이
scrollableArea와 scrollable의 주요 차이점은 사용자 스크롤 동작을 해석하는 방식에 있습니다.
scrollable(원시 델타): 델타는 화면에서 사용자의 입력 (예: 포인터 드래그)의 실제 움직임을 직접 반영합니다.scrollableArea(콘텐츠 중심 델타):delta는 콘텐츠가 사용자의 동작과 함께 이동하는 것처럼 보이도록 스크롤 위치의 선택된 변경사항을 나타내기 위해 의미적으로 반전됩니다. 이는 일반적으로 포인터 이동의 반대입니다.
다음과 같이 생각하면 됩니다. scrollable는 포인터가 이동한 방식을 알려주고 scrollableArea는 포인터 이동을 일반적인 스크롤 가능한 뷰 내에서 콘텐츠가 이동해야 하는 방식으로 변환합니다. 이 반전으로 인해 표준 스크롤 가능한 컨테이너를 구현할 때 scrollableArea가 더 자연스럽게 느껴집니다.
다음 표에는 일반적인 시나리오의 델타 기호가 요약되어 있습니다.
사용자 동작 |
|
|
|---|---|---|
포인터가 위로 이동합니다. |
부정 |
긍정 |
포인터가 아래로 이동합니다. |
긍정 |
부정 |
포인터가 왼쪽으로 이동합니다. |
부정 |
긍정 (RTL의 경우 부정) |
포인터가 오른쪽으로 이동합니다. |
긍정 |
음수 (RTL의 경우 양수) |
(*) scrollableArea 델타 부호에 관한 참고사항: scrollableArea의 델타 부호는 단순한 반전이 아닙니다. 다음과 같은 요소를 지능적으로 고려합니다.
- 방향: 세로 또는 가로
LayoutDirection: LTR 또는 RTL (특히 가로 스크롤에 중요함).reverseScrolling플래그: 스크롤 방향이 반전되었는지 여부입니다.
스크롤 델타를 반전하는 것 외에도 scrollableArea는 콘텐츠를 레이아웃 경계로 클리핑하고 오버스크롤 효과의 렌더링을 처리합니다. 기본적으로 LocalOverscrollFactory에서 제공하는 효과를 사용합니다.
OverscrollEffect 매개변수를 허용하는 scrollableArea 오버로드를 사용하여 이를 맞춤설정하거나 사용 중지할 수 있습니다.
scrollableArea 수정자를 사용해야 하는 경우
horizontalScroll 또는 verticalScroll 수정자나 지연 로드 레이아웃으로 충분히 제공되지 않는 맞춤 스크롤 구성요소를 빌드해야 하는 경우 scrollableArea 수정자를 사용해야 합니다. 여기에는 다음과 같은 사례가 포함되는 경우가 많습니다.
- 맞춤 레이아웃 로직: 스크롤 위치에 따라 항목의 배열이 동적으로 변경되는 경우
- 고유한 시각 효과: 스크롤할 때 변환, 크기 조절 또는 기타 효과를 자녀에게 적용합니다.
- 직접 제어:
verticalScroll또는 지연 로드 레이아웃에서 노출하는 것 이상으로 스크롤 메커니즘을 세밀하게 제어해야 합니다.
scrollableArea를 사용하여 휠과 같은 맞춤 목록 만들기
다음 샘플에서는 scrollableArea를 사용하여 항목이 중앙에서 멀어질 때 크기가 축소되어 '휠과 같은' 시각적 효과를 만드는 맞춤 수직 목록을 빌드하는 방법을 보여줍니다. 이러한 스크롤 종속 변환은 scrollableArea에 완벽한 사용 사례입니다.
scrollableArea를 사용하는 맞춤 세로 목록
@Composable private fun ScrollableAreaSample() { // ... Layout( modifier = Modifier .size(150.dp) .scrollableArea(scrollState, Orientation.Vertical) .background(Color.LightGray), // ... ) { measurables, constraints -> // ... // Update the maximum scroll value to not scroll beyond limits and stop when scroll // reaches the end. scrollState.maxValue = (totalHeight - viewportHeight).coerceAtLeast(0) // Position the children within the layout. layout(constraints.maxWidth, viewportHeight) { // The current vertical scroll position, in pixels. val scrollY = scrollState.value val viewportCenterY = scrollY + viewportHeight / 2 var placeableLayoutPositionY = 0 placeables.forEach { placeable -> // This sample applies a scaling effect to items based on their distance // from the center, creating a wheel-like effect. // ... // Place the item horizontally centered with a layer transformation for // scaling to achieve wheel-like effect. placeable.placeRelativeWithLayer( x = constraints.maxWidth / 2 - placeable.width / 2, // Offset y by the scroll position to make placeable visible in the viewport. y = placeableLayoutPositionY - scrollY, ) { scaleX = scaleFactor scaleY = scaleFactor } // Move to the next item's vertical position. placeableLayoutPositionY += placeable.height } } } } // ...
스크롤 가능한 수정자
scrollable 수정자는 스크롤 수정자와는 다릅니다. 즉, scrollable은 스크롤 동작을 감지하고 델타를 캡처하지만 콘텐츠를 자동으로 오프셋하지는 않습니다. 대신 이 수정자가 올바르게 작동하는 데 필요한 ScrollableState를 통해 사용자에게 위임됩니다.
ScrollableState를 구성할 때는 각 스크롤 단계에서 픽셀 단위 델타를 사용하여 (동작 입력, 부드러운 스크롤 또는 플링으로) 호출할 consumeScrollDelta 함수를 제공해야 합니다. 이 함수는 scrollable 수정자가 있는 중첩 요소가 있는 경우 이벤트가 올바르게 전파되도록 하기 위해 사용된 스크롤 거리를 반환해야 합니다.
다음 스니펫은 동작을 감지하고 오프셋의 숫자 값을 표시하지만 아무 요소도 오프셋하지 않습니다.
@Composable private fun ScrollableSample() { // actual composable state var offset by remember { mutableFloatStateOf(0f) } Box( Modifier .size(150.dp) .scrollable( orientation = Orientation.Vertical, // Scrollable state: describes how to consume // scrolling delta and update offset state = rememberScrollableState { delta -> offset += delta delta } ) .background(Color.LightGray), contentAlignment = Alignment.Center ) { Text(offset.toString()) } }

추천 서비스
- 참고: JavaScript가 사용 중지되어 있으면 링크 텍스트가 표시됩니다.
- 동작 이해하기
CoordinatorLayout를 Compose로 이전- Compose에서 뷰 사용