如何在SwiftUI中访问安全区域大小?

时间:2019-07-19 16:54:36

标签: swiftui

我想在SwiftUI中手动将视图的框架高度设置为屏幕安全区域的大小。容易获得屏幕边界(UIScreen.main.bounds),但是我找不到找到安全区域大小的方法。

4 个答案:

答案 0 :(得分:8)

如果您在 parentView 上使用 edgesIgnoringSafeArea 并且想要访问设备 UISafeAreaInsets,您可以执行以下操作:

代码

private struct SafeAreaInsetsKey: EnvironmentKey {
    static var defaultValue: EdgeInsets {
        (UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.safeAreaInsets ?? .zero).insets
    }
}

extension EnvironmentValues {
    
    var safeAreaInsets: EdgeInsets {
        self[SafeAreaInsetsKey.self]
    }
}

private extension UIEdgeInsets {
    
    var insets: EdgeInsets {
        EdgeInsets(top: top, leading: left, bottom: bottom, trailing: right)
    }
}

使用

struct MyView: View {
    
    @Environment(\.safeAreaInsets) private var safeAreaInsets
    
    var body: some View {
        Text("Ciao")
            .padding(safeAreaInsets)
    }
}

答案 1 :(得分:2)

不确定为什么接受的答案将顶部插入用于放置在底部视图下的视图 - 这些不一样。 此外,如果您更正此“错字”,您将看到 edgesIgnoringSafeArea 调用的 GeometryReader 将对应的值归零。看起来在 iOS 13 上并非如此,但现在是这样,因此您需要在 edgesIgnoringSafeArea 子节点上调用 GeometryReader,并且此代码在 iOS 13 上仍按预期工作:< /p>

GeometryReader { geometry in
    VStack {
        Spacer()
        Color.red
            .frame(
                width: geometry.size.width,
                height: geometry.safeAreaInsets.bottom,
                alignment: .center
            )
            .aspectRatio(contentMode: ContentMode.fit)
    }
    .edgesIgnoringSafeArea(.bottom)
}

答案 2 :(得分:0)

您可以使用GeometryReader访问安全区域。
参见:https://developer.apple.com/documentation/swiftui/geometryreader

struct ContentView : View {

    var body: some View {
        GeometryReader { geometry in
            VStack {
                Spacer()
                Color.red
                    .frame(
                        width: geometry.size.width,
                        height: geometry.safeAreaInsets.top,
                        alignment: .center
                )
                    .aspectRatio(contentMode: ContentMode.fit)
            }
        }
        .edgesIgnoringSafeArea(.bottom)
    }
}

但是,仅供参考:她的安全区域不是大小。这是EdgeInsets

答案 3 :(得分:0)

UIApplication.shared.windows 已弃用,您现在可以使用 connectedScenes:

import SwiftUI

extension UIApplication {
    var keyWindow: UIWindow? {
        connectedScenes
            .compactMap {
                $0 as? UIWindowScene
            }
            .flatMap {
                $0.windows
            }
            .first {
                $0.isKeyWindow
            }
    }
}

private struct SafeAreaInsetsKey: EnvironmentKey {
    static var defaultValue: EdgeInsets {
        UIApplication.shared.keyWindow?.safeAreaInsets.swiftUiInsets ?? EdgeInsets()
    }
}

extension EnvironmentValues {
    var safeAreaInsets: EdgeInsets {
        self[SafeAreaInsetsKey.self]
    }
}

private extension UIEdgeInsets {
    var swiftUiInsets: EdgeInsets {
        EdgeInsets(top: top, leading: left, bottom: bottom, trailing: right)
    }
}

然后在您的视图中使用 Environment 属性来获取安全区域插图:

@Environment(\.safeAreaInsets) private var safeAreaInsets