With SwiftUI 2.0, scroll positioning has become much easier to adapt to most application scenarios. The implementation method is completely different from various folk solutions in the past, and it is not done by setting specific offsets for positioning, but by using IDs to mark positions.
Basic Usage —— Implementing Horizontal Scroll from Right to Left
Swift
struct ScrollReaderTest: View {
var body: some View {
ScrollView(.horizontal) {
// Similar to the usage of GeometryReader, set the scroll positioning area
ScrollViewReader{ proxy in
Rectangle()
.fill(LinearGradient(
gradient: Gradient(colors: [.blue,.red]),
startPoint: .leading,
endPoint: .trailing))
.frame(width: 1000, height: 300, alignment: .center)
.id("rec") // Set ID for the view in ScrollView that needs to be positioned
.onAppear {
// Scroll to the specified ID position, aligning according to the anchor setting
proxy.scrollTo("rec",anchor:.trailing)
}
}
}
}
}
Scroll to Specific Position Using Buttons
Swift
import SwiftUI
struct ScrollReadeTest: View {
private var list = ScrollItem.items(300)
@State private var position:Int = 0
var body: some View {
NavigationView{
ScrollView{
ScrollViewReader{ proxy in
LazyVStack{
ForEach(list,id:\.id){ item in
Text(item.title).id(item.id)
}
}
.onChange(of: position) { positon in
switch position{
case 1:
let id = list.first!.id
withAnimation(Animation.easeInOut){
proxy.scrollTo(id,anchor:.top)
}
case 2:
let id = list[Int(list.count / 2)].id
withAnimation(Animation.easeInOut){
proxy.scrollTo(id,anchor:.center)
}
case 3:
let id = list.last!.id
withAnimation(Animation.easeInOut){
proxy.scrollTo(id,anchor:.bottom)
}
default:
break
}
}
}
}
.navigationTitle("Scroll Positioning")
.toolbar {
ToolbarItem(placement:.automatic) {
HStack{
Button("Top"){
position = 1
}
Button("Middle"){
position = 2
}
Button("End"){
position = 3
}
}
}
}
}
}
}
struct ScrollItem:Identifiable{
var id = UUID()
var title:String
static func items(_ count:Int) -> [ScrollItem]{
var result:[ScrollItem] = []
for i in 0..<count{
result.append(ScrollItem(title:String("index:\(i) title:\(Int.random(in: 1000...5000))")))
}
return result
}
}
Drawback
There is no simple way to record the current scroll position.