ScrollView
Skip support for SwiftUI.ScrollView ↗.
The following example screens and source code is from SkipUI’s
Showcase sample app
ScrollViewPlayground.swift ↗
import SwiftUI
enum ScrollViewPlaygroundType: String, CaseIterable { case vertical case horizontal case readerLazyVStack case readerLazyHStack case readerList case readerStaticList case readerLazyVGrid case readerLazyHGrid
var title: String { switch self { case .vertical: return "Vertical" case .horizontal: return "Horizontal" case .readerLazyVStack: return "ScrollViewReader: LazyVStack" case .readerLazyHStack: return "ScrollViewReader: LazyHStack" case .readerList: return "ScrollViewReader: ForEach List" case .readerStaticList: return "ScrollViewReader: Static List" case .readerLazyVGrid: return "ScrollViewReader: LazyVGrid" case .readerLazyHGrid: return "ScrollViewReader: LazyHGrid" } }}
struct ScrollViewPlayground: View { var body: some View { List(ScrollViewPlaygroundType.allCases, id: \.self) { type in NavigationLink(type.title, value: type) } .toolbar { PlaygroundSourceLink(file: "ScrollViewPlayground.swift") } .navigationDestination(for: ScrollViewPlaygroundType.self) { switch $0 { case .vertical: VerticalScrollViewPlayground() .navigationTitle($0.title) case .horizontal: HorizontalScrollViewPlayground() .navigationTitle($0.title) case .readerLazyVStack: ScrollViewReaderLazyVStackPlayground() .navigationTitle($0.title) case .readerLazyHStack: ScrollViewReaderLazyHStackPlayground() .navigationTitle($0.title) case .readerList: ScrollViewReaderListPlayground() .navigationTitle($0.title) case .readerStaticList: ScrollViewReaderStaticListPlayground() .navigationTitle($0.title) case .readerLazyVGrid: ScrollViewReaderLazyVGridPlayground() .navigationTitle($0.title) case .readerLazyHGrid: ScrollViewReaderLazyHGridPlayground() .navigationTitle($0.title) } } }}
private struct VerticalScrollViewPlayground: View { var body: some View { ScrollView { VStack { ForEach(0..<30) { i in Text("View: \(i)") .padding() } } } }}
private struct HorizontalScrollViewPlayground: View { var body: some View { ScrollView(.horizontal) { HStack { ForEach(0..<30) { i in Text("View: \(i)") .padding() } } } }}
private struct ScrollViewReaderLazyVStackPlayground: View { var body: some View { ScrollViewReader { proxy in VStack(spacing: 16) { ScrollViewReaderJumpButtons(proxy: proxy) .padding([.top, .bottom]) ScrollView { LazyVStack { ForEach(0..<30, id: \.self) { i in Text("View: \(i)") .padding() } } } .border(.primary, width: 1) } } }}
private struct ScrollViewReaderLazyHStackPlayground: View { var body: some View { ScrollViewReader { proxy in VStack(spacing: 16) { ScrollViewReaderJumpButtons(proxy: proxy) .padding([.top, .bottom]) ScrollView(.horizontal) { LazyHStack { ForEach(0..<30, id: \.self) { i in Text("View: \(i)") .padding() } } } .border(.primary, width: 1) } } }}
private struct ScrollViewReaderListPlayground: View { var body: some View { ScrollViewReader { proxy in VStack(spacing: 16) { ScrollViewReaderJumpButtons(proxy: proxy) .padding([.top, .bottom]) List { Section("Section 0") { ForEach(0..<10, id: \.self) { i in Text("View: \(i)") } } Section("Section 1") { ForEach(10..<20, id: \.self) { i in Text("View: \(i)") } } Section("Section 2") { ForEach(20..<30, id: \.self) { i in Text("View: \(i)") } } } .border(.primary, width: 1) } } }}
private struct ScrollViewReaderStaticListPlayground: View { var body: some View { ScrollViewReader { proxy in VStack(spacing: 16) { ScrollViewReaderJumpButtons(proxy: proxy) .padding([.top, .bottom]) List { Section("Section 0") { Text("View 0") .id(0) Text("View 1") .id(1) Text("View 2") .id(2) Text("View 3") .id(3) Text("View 4") .id(4) Text("View 5") .id(5) Text("View 6") .id(6) Text("View 7") .id(7) Text("View 8") .id(8) Text("View 9") .id(9) } Section("Section 1") { Text("View 10") .id(10) Text("View 11") .id(11) Text("View 12") .id(12) Text("View 13") .id(13) Text("View 14") .id(14) Text("View 15") .id(15) Text("View 16") .id(16) Text("View 17") .id(17) Text("View 18") .id(18) Text("View 19") .id(19) } Section("Section 2") { Text("View 20") .id(20) Text("View 21") .id(21) Text("View 22") .id(22) Text("View 23") .id(23) Text("View 24") .id(24) Text("View 25") .id(25) Text("View 26") .id(26) Text("View 27") .id(27) Text("View 28") .id(28) Text("View 29") .id(29) } } .border(.primary, width: 1) } } }}
private struct ScrollViewReaderLazyVGridPlayground: View { var body: some View { ScrollViewReader { proxy in VStack(spacing: 16) { ScrollViewReaderJumpButtons(proxy: proxy) .padding([.top, .bottom]) ScrollView { LazyVGrid(columns: [GridItem(.adaptive(minimum: 200))]) { ForEach(0..<30) { index in ZStack { Color.yellow Text(String(describing: index)) } .frame(height: 200) } } } .border(.primary, width: 1) } } }}
private struct ScrollViewReaderLazyHGridPlayground: View { var body: some View { ScrollViewReader { proxy in VStack(spacing: 16) { ScrollViewReaderJumpButtons(proxy: proxy) .padding([.top, .bottom]) ScrollView(.horizontal) { LazyHGrid(rows: [GridItem(.adaptive(minimum: 200))]) { ForEach(0..<30) { index in ZStack { Color.yellow Text(String(describing: index)) } .frame(width: 200) } } } .border(.primary, width: 1) } } }}
private struct ScrollViewReaderJumpButtons: View { let proxy: ScrollViewProxy
var body: some View { VStack(spacing: 16) { HStack(spacing: 16) { Button("Scroll to 0") { proxy.scrollTo(0) } Button("Animated") { withAnimation { proxy.scrollTo(0) } } } .padding(.top) HStack(spacing: 16) { Button("Scroll to 15") { proxy.scrollTo(15) } Button("Animated") { withAnimation { proxy.scrollTo(15) } } } HStack(spacing: 16) { Button("Scroll to 29") { proxy.scrollTo(29) } Button("Animated") { withAnimation { proxy.scrollTo(29) } } } } }}