Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
271 views
in Technique[技术] by (71.8m points)

swift - How to access safeAreaInsets of another CoordinateSpace in SwiftUI

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.

enter image description here enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...