如何访问 SwiftUI 中的安全区域大小?
How to access safe area size in SwiftUI?
我想在 SwiftUI 中手动将视图的框架高度设置为屏幕安全区域的大小。获取屏幕边界很容易(UIScreen.main.bounds
),但我找不到访问安全区域大小的方法。
您可以使用 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
.
不确定为什么已接受的答案将顶部插图用于放置在底部视图下方的视图 - 它们不一样。
此外,如果您更正此“拼写错误”,您将看到 edgesIgnoringSafeArea
调用 GeometryReader
将相应的值归零。看起来 iOS 13 不是这种情况,但现在是,所以你需要在 GeometryReader
child 上调用 edgesIgnoringSafeArea
,而这段代码仍然在 iOS 13:
上按预期工作
GeometryReader { geometry in
VStack {
Spacer()
Color.red
.frame(
width: geometry.size.width,
height: geometry.safeAreaInsets.bottom,
alignment: .center
)
.aspectRatio(contentMode: ContentMode.fit)
}
.edgesIgnoringSafeArea(.bottom)
}
如果您在 parentView 上使用 edgesIgnoringSafeArea
并且想要访问设备 UISafeAreaInsets
,您可以执行以下操作:
代码
private struct SafeAreaInsetsKey: EnvironmentKey {
static var defaultValue: EdgeInsets {
(UIApplication.shared.windows.first(where: { [=10=].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)
}
}
UIApplication.shared.windows 已弃用,您现在可以使用 connectedScenes:
import SwiftUI
extension UIApplication {
var keyWindow: UIWindow? {
connectedScenes
.compactMap {
[=10=] as? UIWindowScene
}
.flatMap {
[=10=].windows
}
.first {
[=10=].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(\.safeAreaInsets) private var safeAreaInsets
您还可以创建自定义 EnvironmentValue
并从“初始 View
”传递安全区域插入。这非常适合我!
正在创建EnvironmentValue
private struct SafeAreaInsetsEnvironmentKey: EnvironmentKey {
static let defaultValue: (top: CGFloat, bottom: CGFloat) = (0, 0)
}
extension EnvironmentValues {
var safeAreaInsets: (top: CGFloat, bottom: CGFloat) {
get { self[SafeAreaInsetsEnvironmentKey.self] }
set { self[SafeAreaInsetsEnvironmentKey.self] = newValue }
}
}
设置
想法是在任何潜在的 View
parent 使用 .edgesIgnoringSafeArea
之前执行此操作,这是它工作所必需的。例如:
@main
struct YourApp: App {
@State private var safeAreaInsets: (top: CGFloat, bottom: CGFloat) = (0, 0)
var body: some Scene {
WindowGroup {
ZStack {
GeometryReader { proxy in
Color.clear.onAppear {
safeAreaInsets = (proxy.safeAreaInsets.top, proxy.safeAreaInsets.bottom)
}
}
ContentView()
.environment(\.safeAreaInsets, safeAreaInsets)
}
}
}
}
用法
struct SomeChildView: View {
@Environment(\.safeAreaInsets) var safeAreaInsets
...
}
我想在 SwiftUI 中手动将视图的框架高度设置为屏幕安全区域的大小。获取屏幕边界很容易(UIScreen.main.bounds
),但我找不到访问安全区域大小的方法。
您可以使用 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
.
不确定为什么已接受的答案将顶部插图用于放置在底部视图下方的视图 - 它们不一样。
此外,如果您更正此“拼写错误”,您将看到 edgesIgnoringSafeArea
调用 GeometryReader
将相应的值归零。看起来 iOS 13 不是这种情况,但现在是,所以你需要在 GeometryReader
child 上调用 edgesIgnoringSafeArea
,而这段代码仍然在 iOS 13:
GeometryReader { geometry in
VStack {
Spacer()
Color.red
.frame(
width: geometry.size.width,
height: geometry.safeAreaInsets.bottom,
alignment: .center
)
.aspectRatio(contentMode: ContentMode.fit)
}
.edgesIgnoringSafeArea(.bottom)
}
如果您在 parentView 上使用 edgesIgnoringSafeArea
并且想要访问设备 UISafeAreaInsets
,您可以执行以下操作:
代码
private struct SafeAreaInsetsKey: EnvironmentKey {
static var defaultValue: EdgeInsets {
(UIApplication.shared.windows.first(where: { [=10=].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)
}
}
UIApplication.shared.windows 已弃用,您现在可以使用 connectedScenes:
import SwiftUI
extension UIApplication {
var keyWindow: UIWindow? {
connectedScenes
.compactMap {
[=10=] as? UIWindowScene
}
.flatMap {
[=10=].windows
}
.first {
[=10=].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(\.safeAreaInsets) private var safeAreaInsets
您还可以创建自定义 EnvironmentValue
并从“初始 View
”传递安全区域插入。这非常适合我!
正在创建EnvironmentValue
private struct SafeAreaInsetsEnvironmentKey: EnvironmentKey {
static let defaultValue: (top: CGFloat, bottom: CGFloat) = (0, 0)
}
extension EnvironmentValues {
var safeAreaInsets: (top: CGFloat, bottom: CGFloat) {
get { self[SafeAreaInsetsEnvironmentKey.self] }
set { self[SafeAreaInsetsEnvironmentKey.self] = newValue }
}
}
设置
想法是在任何潜在的 View
parent 使用 .edgesIgnoringSafeArea
之前执行此操作,这是它工作所必需的。例如:
@main
struct YourApp: App {
@State private var safeAreaInsets: (top: CGFloat, bottom: CGFloat) = (0, 0)
var body: some Scene {
WindowGroup {
ZStack {
GeometryReader { proxy in
Color.clear.onAppear {
safeAreaInsets = (proxy.safeAreaInsets.top, proxy.safeAreaInsets.bottom)
}
}
ContentView()
.environment(\.safeAreaInsets, safeAreaInsets)
}
}
}
}
用法
struct SomeChildView: View {
@Environment(\.safeAreaInsets) var safeAreaInsets
...
}