我想在SwiftUI中手动将视图的框架高度设置为屏幕安全区域的大小。很容易获得屏幕的边界(UIScreen.main.bounds),但我找不到访问安全区域大小的方法。
UIScreen.main.bounds
368yc8dk1#
您可以使用GeometryReader访问安全区域。请参见:https://developer.apple.com/documentation/swiftui/geometryreader。
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。
EdgeInsets
xghobddn2#
如果在parentView上使用edgesIgnoringSafeArea,并且希望访问设备UISafeAreaInsets,则可以执行以下操作:
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) } }
9nvpjoqh3#
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) } }
然后使用View中的Environment属性获取安全区域插图:
@Environment(\.safeAreaInsets) private var safeAreaInsets
nlejzf6q4#
不知道为什么接受的答案使用顶部插入的一个视图放在下面的一个-这是不一样的。另外,如果你纠正这个“错别字”,你会看到edgesIgnoringSafeArea调用了一个GeometryReader零相应的值。看起来不是这样的iOS 13回来,但现在它是,所以你需要调用一个GeometryReader孩子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) }
frebpwbc5#
您也可以创建一个自定义的EnvironmentValue并从“初始View“传递安全区域插入。这非常适合我!
EnvironmentValue
View
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父代使用.edgesIgnoringSafeArea之前执行此操作,这是它工作所必需的。例如:
.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 ... }
ff29svar6#
extension UIScreen { static var topSafeArea: CGFloat { let keyWindow = UIApplication.shared.connectedScenes .filter({$0.activationState == .foregroundActive}) .map({$0 as? UIWindowScene}) .compactMap({$0}) .first?.windows .filter({$0.isKeyWindow}).first return (keyWindow?.safeAreaInsets.top) ?? 0 } }
用法:
UIScreen.topSafeArea
6条答案
按热度按时间368yc8dk1#
您可以使用
GeometryReader
访问安全区域。请参见:https://developer.apple.com/documentation/swiftui/geometryreader。
不过顺便说一句:安全区不是一个尺寸,它是一个
EdgeInsets
。xghobddn2#
如果在parentView上使用
edgesIgnoringSafeArea
,并且希望访问设备UISafeAreaInsets
,则可以执行以下操作:9nvpjoqh3#
UIApplication.shared.windows 已弃用,您现在可以使用connectedScenes:
然后使用View中的Environment属性获取安全区域插图:
nlejzf6q4#
不知道为什么接受的答案使用顶部插入的一个视图放在下面的一个-这是不一样的。另外,如果你纠正这个“错别字”,你会看到
edgesIgnoringSafeArea
调用了一个GeometryReader
零相应的值。看起来不是这样的iOS 13回来,但现在它是,所以你需要调用一个GeometryReader
孩子edgesIgnoringSafeArea
代替,这段代码在iOS 13上仍然可以正常工作:frebpwbc5#
您也可以创建一个自定义的
EnvironmentValue
并从“初始View
“传递安全区域插入。这非常适合我!正在创建
EnvironmentValue
设置
我们的想法是在任何潜在的
View
父代使用.edgesIgnoringSafeArea
之前执行此操作,这是它工作所必需的。例如:用法
ff29svar6#
用法: