【发布时间】:2019-11-28 16:48:15
【问题描述】:
我想手动将 SwiftUI 中视图的框架高度设置为屏幕安全区域的大小。获取屏幕边界很容易(UIScreen.main.bounds),但我找不到访问安全区域大小的方法。
【问题讨论】:
我想手动将 SwiftUI 中视图的框架高度设置为屏幕安全区域的大小。获取屏幕边界很容易(UIScreen.main.bounds),但我找不到访问安全区域大小的方法。
【问题讨论】:
不确定为什么接受的答案使用顶部插图作为放置在底部下方的视图 - 这些不一样。
此外,如果您更正此“错字”,您会看到在 GeometryReader 上调用的 edgesIgnoringSafeArea 会将相应的值归零。看起来在 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)
}
【讨论】:
GeometryReader 将对应值归零”中遗漏了一个词?无论如何,我解决了; SwiftUI 是否有针对此类情况的“无操作”容器,或者即使您在技术上不需要,您是否只使用 VStack?
GeometryReader 之外禁用edgesIgnoringSafeArea,你就不能在里面获得geometry.safeAreaInsets(值将为零)。使用geometry,我们可以获得所需的尺寸,但为了将视图放在正确的位置,我使用VStack:Spacer 占用了所有剩余空间并将我的视图向下推。
VStack 很奇怪。不过,这与最初的问题并没有真正的密切关系。
VStack 并不是一个坏习惯。绘制这样的视图不会是高负载操作。你可以设置一个父视图的对齐方式,但是如果你想让不同的子视图有不同的对齐方式,你可以使用这个方法。
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
【讨论】:
如果您在 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)
}
}
【讨论】:
您可以使用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。
【讨论】: