I'm trying to write a view extension with a ViewModifier
that allows me to position any view in the CoordinateSpace
of another. My code so far does work, except that it has alignment issues if one of the CoordinateSpaces has a safe area.
I'm able to fix it by adding .edgesIgnoringSafeArea(.all)
to the target CoordinateSpace
but I would like to use this extension without having to worry about the safe area of the other CoordinateSystems.
To clarify my code:
In my code the first circle is inside a HStack
and GeometryReader
and sets a CoordinateSpace
called "otherSpace"
.
The circle in the other HStack sets its position based on the position in "otherSpace"
. The first HStack
and GeometryReader
is on top, and has a top edgeInset
of 20. The second one has none. Looking at the values the GeometryProxy
(in the ViewModifier
) gives me, I can't find a way to figure out if there is a way to calculate the edgeInsets.
Here is my code so far:
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
HStack {
GeometryReader() { geometryProxy in
Circle()
.stroke(lineWidth: 3)
.fill(Color.blue)
.frame(width: 100, height: 100, alignment: .center)
.coordinateSpace(name: "otherSpace")
.position(CGPoint(x: 100, y: 100))
.edgesIgnoringSafeArea(.all) //I'd like a way not to use this.
.onAppear() {
}
}.background(Color.green)
}
HStack {
Circle()
.foregroundColor(.red)
.frame(width: 100, height: 100, alignment: .center)
.position(CGPoint(x: 100, y: 100), in: .named("otherSpace"))
}
}
}
}
extension View {
func position(_ position: CGPoint, in coordinateSpace: CoordinateSpace) -> some View {
ModifiedContent(content: self, modifier: AbsolutePosition(position: position, coordinateSpace: coordinateSpace))
}
}
struct AbsolutePosition: ViewModifier {
@State var position: CGPoint
let coordinateSpace: CoordinateSpace
@State var localPosition: CGPoint = .zero
@State var targetPosition: CGPoint = .zero
func body(content: Content) -> some View {
GeometryReader { geometry in
content.onAppear() {
localPosition = geometry.frame(in: .local).origin
targetPosition = geometry.frame(in: coordinateSpace).origin
position.x = localPosition.x - targetPosition.x + position.x
position.y = localPosition.y - targetPosition.y + position.y
}.position(position)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
UPDATE with images.
The first image shows the result when using .edgesIgnoringSafeArea(.all)
on the target circle. I want to get to this result no matter if the target circle (CoordinateSpace) has a safe area or not. But when I remove .edgesIgnoringSafeArea(.all)
I get the 2nd image as a result because my extension doesn't know if there is a safe area or not and always calculates as if there is none.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…