I was playing around with .position(x:y:)
and CoordinateSpace.global
and I came across something that confused me.
I was trying to determine the coordinates of the origin of a ZStack in the global coordinate space. However, when I placed a dot on those coordinates, it didn't line up with the top left corner of the ZStack.
This was the code I used:
struct Test: View {
var body: some View {
ZStack {
Image(systemName: "circle.fill")
.resizable()
.frame(width: 5, height: 5)
.foregroundColor(.red)
.position(x: 177, y: 423) // This is from 'frame.origin.x' and 'frame.origin.y'
ZStack { // Trying to determine this ZStack's coordinates in the global coordinate space
GeometryReader { geometry -> AnyView in // Used to retrieve the coordinates using `geometry` and then returning a Text so I can see the coordinates on screen
let frame = geometry.frame(in: CoordinateSpace.global)
return AnyView(Text("\(frame.origin.x), \(frame.origin.y)").fixedSize(horizontal: false, vertical: true))
}
}
.frame(width: 60, height: 60)
}
}
}
And this is where the dot showed up:
Does anyone know why it showed up at that weird place when it should have appeared on the top left of the ZStack? I thought the origin was supposed to be at the top left of a view?
You calculate frame by geometry reader in global coordinate space but Image is placed in outer ZStack coordinate space, that is why misplacement.
To make it work as expected (accepting for test purpose hardcoded coordinates) the coordinates should be made in one coordinate space.
Here is a solution
var body: some View {
ZStack {
Image(systemName: "circle.fill")
.resizable()
.frame(width: 5, height: 5)
.foregroundColor(.red)
.position(x: 177, y: 379) // This is from 'frame.origin.x' and 'frame.origin.y'
ZStack {
GeometryReader { geometry -> AnyView in
let frame = geometry.frame(in: .named("test")) // << here !!
return AnyView(Text("\(frame.origin.x), \(frame.origin.y)")
.fixedSize(horizontal: false, vertical: true))
}
}
.frame(width: 60, height: 60)
}.coordinateSpace(name: "test") // << here !!
}