In a giant ScrollView, I want to place Circles, and scroll to them so that, when scrolled, they end up in the middle of the screen, one after another.
I can position the Circles either by using .position, .offset or .padding. I have positioned them (300,300) away from one-another, and so that none of them are on screen when the view is loaded.
When I scroll to the ones positioned with .position or .offset, the ScrollView scrolls to the top left. .offset scrolls with an inset, .position all the way. When I scroll to the one positioned with .padding, it is not centred.
What am I doing wrong here? Why will none of my three attempts scroll so that the circle in question is placed in the middle of the ScrollView?
struct CanvasTester: View {
@State var i = 0
var body: some View {
ZStack(alignment: .topLeading) {
ScrollViewReader { scrollView in
ScrollView([.horizontal, .vertical]) {
ZStack(alignment: .topLeading) {
Spacer()
.frame(width: 4096, height: 4096)
.background(Color.yellow)
.task {
@Sendable func f() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
withAnimation {
scrollView.scrollTo("circle\(i+1)", anchor: .center)
self.i = (self.i + 1) % 3
}
f()
}
}
f()
}
Circle()
.stroke(Color.blue, lineWidth: 4)
.frame(width: 44, height: 44)
.offset(x: 1500, y: 1500)
.id("circle1")
Circle()
.stroke(Color.green, lineWidth: 4)
.frame(width: 44, height: 44)
.position(x: 1800, y: 1800)
.id("circle2")
Circle()
.stroke(Color.red, lineWidth: 4)
.frame(width: 44, height: 44)
.padding([.top, .leading], 2100)
.id("circle3")
}
}
}
Text("#\(i+1)")
}
}
}
Quick run-through the code: I have a ScrollReader encapsulating a ScrollView that scrolls both directions and is 4096x4096. It has a yellow background that on draw launches a function that every second scrolls to the view with either ID "circle1", "circle2" or "circle3". Then follow the three circles with those labels, and finally a label I the top left corner to indicate what color number the ID has.