gpt4 book ai didi

SwiftUI - 在不修改 View 大小的情况下使用 GeometryReader

转载 作者:搜寻专家 更新时间:2023-11-01 06:51:37 60 4
gpt4 key购买 nike

我有一个标题 View ,它使用 edgesIgnoringSafeArea 将其背景扩展到状态栏下方。要正确对齐标题​​ View 的内容/ subview ,我需要来自 GeometryReadersafeAreaInsets。但是,当使用 GeometryReader 时,我的 View 不再具有合适的尺寸。

不使用GeometryReader的代码

struct MyView : View {
var body: some View {
VStack(alignment: .leading) {
CustomView()
}
.padding(.horizontal)
.padding(.bottom, 64)
.background(Color.blue)
}
}

预览

Expected

代码使用 GeometryReader

struct MyView : View {
var body: some View {
GeometryReader { geometry in
VStack(alignment: .leading) {
CustomView()
}
.padding(.horizontal)
.padding(.top, geometry.safeAreaInsets.top)
.padding(.bottom, 64)
.background(Color.blue)
.fixedSize()
}
}
}

预览

enter image description here

有没有一种方法可以在不修改底层 View 大小的情况下使用 GeometryReader

最佳答案

标题中问题的答案:

  • 可以将 GeometryReader 包装在 .overlay().background() 中。这样做将减轻 GeometryReader 的布局更改效果。 View 将正常布局,GeometryReader 将扩展到 View 的完整大小,并将 geometry 发送到其内容构建器闭包中。
  • 也可以设置 GeometryReader 的 frame 来阻止它急于展开。

例如,此示例通过将 GeometryReader 包裹在覆盖层中来呈现蓝色矩形和位于矩形高度 3/4 处的“Hello world”文本(而不是矩形填满所有可用空间):

struct MyView : View {
var body: some View {
Rectangle()
.fill(Color.blue)
.frame(height: 150)
.overlay(GeometryReader { geo in
Text("Hello world").padding(.top, geo.size.height * 3 / 4)
})
Spacer()
}
}

另一个通过在 GeometryReader 上设置框架来实现相同效果的示例:

struct MyView : View {
var body: some View {
GeometryReader { geo in
Rectangle().fill(Color.blue)
Text("Hello world").padding(.top, geo.size.height * 3 / 4)
}
.frame(height: 150)

Spacer()
}
}

Render with "Hello world" on 3/4th the height of a blue rectangle.

但是,有一些注意事项/不是很明显的行为

1

View modifiers 适用于它们应用之前的所有内容,而不适用于之后的任何内容。在 .edgesIgnoringSafeArea(.all) 之后添加的叠加层/背景将遵守安全区域(不参与忽略安全区域)。

此代码在安全区域内呈现“Hello world”,而蓝色矩形忽略安全区域:

struct MyView : View {
var body: some View {
Rectangle()
.fill(Color.blue)
.frame(height: 150)
.edgesIgnoringSafeArea(.all)
.overlay(VStack {
Text("Hello world")
Spacer()
})

Spacer()
}
}

Render of "Hello world" inside the safe area.

2

.edgesIgnoringSafeArea(.all) 应用到背景使 GeometryReader 忽略 SafeArea:

struct MyView : View {
var body: some View {
Rectangle()
.fill(Color.blue)
.frame(height: 150)
.overlay(GeometryReader { geo in
VStack {
Text("Hello world")
// No effect, safe area is set to be ignored.
.padding(.top, geo.safeAreaInsets.top)
Spacer()
}
})
.edgesIgnoringSafeArea(.all)

Spacer()
}
}

Render of "Hello world" ignoring the safe area.

可以通过添加多个叠加层/背景来组成多个布局。

3

测量的几何图形将可用于 GeometryReader 的内容。不以 parent 或 sibling 的观点;即使值被提取到 State 或 ObservableObject 中。如果发生这种情况,SwiftUI 将发出运行时警告:

struct MyView : View {
@State private var safeAreaInsets = EdgeInsets()

var body: some View {
Text("Hello world")
.edgesIgnoringSafeArea(.all)
.background(GeometryReader(content: set(geometry:)))
.padding(.top, safeAreaInsets.top)
Spacer()
}

private func set(geometry: GeometryProxy) -> some View {
self.safeAreaInsets = geometry.safeAreaInsets
return Color.blue
}
}

Runtime warning "Modifying state during view update, this will cause undefined behavior."

关于SwiftUI - 在不修改 View 大小的情况下使用 GeometryReader,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56859095/

60 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com