ScrollView
스크롤 상태 추적과 오프셋 감지가 가능한 커스텀 스크롤 뷰입니다.
기본 SwiftUI 스크롤 뷰를 확장하여 스크롤 상태 추적, 오프셋 감지, 새로고침 등 추가 기능을 제공합니다.
스크롤 위치는 스크롤 뷰 안에서만 추적하고, 바깥에는 필요한 만큼만 알립니다. 오프셋에서 필요한 값만 뽑아 받으려면 onScrollOffsetChange(for:transform:action:)를, 크기와 오프셋을 함께 읽으려면 ScrollView.Geometry를 씁니다.
Note
콘텐츠 오프셋은 최상단에서
0이고, 아래(가로는 오른쪽)로 스크롤할수록 음수가 됩니다. 당겨서 새로고침처럼 최상단 너머로 당기면 양수가 됩니다.
struct ScrollStatus
스크롤 뷰의 상태를 추적하는 구조체입니다.
-
Overview
스크롤 방향, 스크롤 뷰 크기, 콘텐츠 크기, 오프셋 등의 정보를 포함합니다.
Note
deprecated된 init(scrollStatus:onOffsetChanged:content:)에서만 쓰입니다. 새 코드는 ScrollView.Geometry를 쓰세요.
init(axis: Axis, scrollViewSize: CGSize, contentSize: CGSize, contentOffset: CGPoint)
스크롤 상태를 초기화합니다.
-
Parameters
var axis: Axis
스크롤 방향
var contentOffset: CGPoint
콘텐츠 오프셋
var contentSize: CGSize
콘텐츠 크기
var reachedEnd: Bool
스크롤이 끝(세로는 바닥, 가로는 오른쪽 끝)에 도달했는지 여부입니다.
-
Discussion
ActionArea의 상단 그라데이션은 이 값으로 표시 여부를 정합니다.
var scrollViewSize: CGSize
스크롤 뷰 크기
init(content: () -> any View)
init(content: () -> any View)() -> any View를 돌려주는 클로저로 스크롤 뷰를 초기화합니다.
Deprecated
콘텐츠 클로저가 any View를 돌려주지 않게 바꾸고 init(content:)를 쓰세요.
-
Parameters
-
Discussion
any View는View를 따르지 않아 init(content:)로 넘길 수 없습니다. 이전 init에 이런 클로저를 넘기던 호출을 받아 두려고 남긴 경로이며,@ViewBuilder클로저는 이 init으로 오지 않습니다.
init<Content>(content: () -> Content)
스크롤 뷰를 초기화합니다.
-
Parameters
init<Content>(geometry: Geometry, content: () -> Content)
스크롤 상태를 ScrollView.Geometry에 기록하는 스크롤 뷰를 초기화합니다.
-
Parameters
-
Discussion
geometry는 값이 바뀐 속성만 알리므로, 그 속성을 읽는 뷰만 다시 그려집니다. 스크롤마다 바뀌는 contentOffset을 화면 전체의body에서 읽으면 스크롤하는 내내 화면 전체가 다시 그려지니, 읽는 부분을 작은 하위 뷰로 떼어 내세요. reachedEnd도 오프셋을 읽어 스크롤마다 다시 그려집니다.Bool하나만 필요하면 onScrollOffsetChange(for:transform:action:)가 값이 바뀔 때만 알려 더 쌉니다.
init(onOffsetChanged: (CGPoint) -> Void, content: () -> any View)
init(onOffsetChanged: (CGPoint) -> Void, content: () -> any View)스크롤 뷰를 초기화합니다.
Deprecated
스크롤 틱마다 불립니다. init(content:)에 onScrollOffsetChange(for:transform:action:)를 붙여 필요한 값이 바뀔 때만 받으세요.
-
Parameters
-
Discussion
Important
스크롤할 때마다
onOffsetChanged가 불립니다. 그 안에서 상태를 바꾸면 그 상태를 쥔 뷰의body전체가 스크롤 틱마다 다시 그려집니다. 오프셋에서 필요한 값만 받으려면 onScrollOffsetChange(for:transform:action:)를 쓰세요.
init(scrollStatus: Binding<ScrollStatus>?, onOffsetChanged: (CGPoint) -> Void, content: () -> any View)
init(scrollStatus: Binding<ScrollStatus>?, onOffsetChanged: (CGPoint) -> Void, content: () -> any View)스크롤 뷰를 초기화합니다.
Deprecated
스크롤마다 바인딩을 쥔 뷰 전체가 다시 그려집니다. init(content:)에 onScrollOffsetChange(for:transform:action:)를 붙이거나 init(geometry:content:)를 쓰세요.
-
Parameters
-
Discussion
Important
스크롤할 때마다
scrollStatus에 값을 써서 바인딩을 쥔 뷰의body전체가 다시 그려집니다. 오프셋에서 필요한 값만 받으려면 onScrollOffsetChange(for:transform:action:)를, 스크롤 상태를 통째로 읽어야 하면 init(geometry:content:)를 쓰세요.
var body: some View
뷰의 내용과 동작을 정의합니다.
func axis(Axis) -> ScrollView
스크롤 방향을 설정합니다.
-
Parameters
-
Return Value
수정된 스크롤 뷰
func hidesIndicators(Bool) -> ScrollView
스크롤 인디케이터 표시 여부를 설정합니다.
-
Parameters
-
Return Value
수정된 스크롤 뷰
func onRefresh(() async -> Void) -> ScrollView
당겨서 새로고침 동작을 설정합니다.
-
Parameters
-
Return Value
수정된 스크롤 뷰
func onScrollOffsetChange<T>(for: T.Type, transform: (_ offset: CGPoint) -> T, action: (_ oldValue: T, _ newValue: T) -> Void) -> ScrollView
스크롤 오프셋에서 뽑은 값이 바뀔 때 동작을 실행합니다.
-
Parameters
-
Return Value
수정된 스크롤 뷰
-
Discussion
transform은 스크롤할 때마다 불리지만action은 그 결과가 달라질 때만 불립니다. 필요한 만큼으로 값을 줄일수록action이 덜 불리고, 그 안에서 바꾼 상태 때문에 다시 그려지는 일도 줄어듭니다.transform이 바깥 값을 쓰면 그 값만 바뀌어도 결과가 달라질 수 있습니다. 이때도action이 불립니다.action은 직전 렌더에서 만든 클로저가 불리므로, 상태는@State·@Binding으로 바꾸고 부모가 넘긴let값은 캡처하지 마세요. 여러 번 붙이면 붙인 순서대로 각각 동작합니다.Note
처음 그려질 때는
action이 불리지 않습니다. 상태의 초깃값은 오프셋이.zero일 때의 결과에 맞춰 두세요.
Conforms To
Swift.Sendable
SwiftUICore.View