I have a horizontal scroll with some fixed size content cells, how can I make it so that it's a swipe to go to the next/previous cell? Similar to a tinder swipe but all remain in the scroll view. I want the cells to 'click' to the leading edge of the Hstack
struct ContentView: View {
let content = ["Hello", "World", "How", "Are", "You"]
var body: some View {
ScrollView(.horizontal) {
HStack {
ForEach(content) { str in
Text(str)
.frame(width: 200, height: 200, alignment: .center)
.background(Color.green)
}
}
}
}
}
Try applying .scrollTargetLayout()
to the HStack
and .scrollTargetBehavior(.paging)
to the ScrollView
. Also:
ForEach
had an error, using .enumerated()
is a way to fix this..containerRelativeFrame(.horizontal)
to set the width of each view to the width of the containing ScrollView
.HStack
has spacing: 0
. So if you would like spacing between the pages, use padding to achieve it..scrollPosition
modifier..onChange
handler can be used to detect a change of page id. This is where you could trigger an impact effect (ref. your question in a comment).@State private var pageId: Int?
var body: some View {
ScrollView(.horizontal) {
HStack(spacing: 0) {
ForEach(Array(content.enumerated()), id: \.offset) { offset, str in
Text(str)
.frame(height: 200, alignment: .center)
.frame(maxWidth: .infinity)
.background(
RoundedRectangle(cornerRadius: 10)
.fill(.green)
)
.padding(.horizontal, 10)
.containerRelativeFrame(.horizontal)
}
}
.scrollTargetLayout()
}
.scrollPosition(id: $pageId)
.scrollTargetBehavior(.paging)
.onChange(of: pageId) { oldVal, newVal in
if let newVal {
print("page \(newVal) selected")
}
}
}