我有一个宽度和高度固定的主视图,因为该视图将转换为PDF。接下来,我有一个子视图数组,这些子视图将垂直堆叠在主视图中。可能存在的子视图超出了主视图的容纳能力,因此我需要一种方法来确保我不超过主视图的总高度。例如,如果我在数组中有八个子视图,但只有三个将适合主视图,那么我需要在三个之后停止添加子视图。其余子视图将在新的主视图上重新开始该过程。
我的问题是,如果我使用GeometryReader来获取视图的高度,则首先必须添加它。但是,一旦添加了视图,就来不及确定它是否超过了可用的总高度。
下面显示了如何在添加每个视图时获得它们的高度。我知道这没什么大不了的,但是我很困。
更新: 我目前的策略是创建一个临时视图,在其中可以添加子视图并返回仅包含适合的子视图的数组。
printf("scan b: %f\n", *b);
答案 0 :(得分:1)
您可以在一处获得总高度,如下所示:
VStack {
ForEach(tasks) { task in
TaskRowView(task: task)
}
}
.overlay(
GeometryReader { geo in
// geo.size.height // << move it here and get total height at once
})
答案 1 :(得分:0)
一种可能的解决方案是使用查看首选项。
您可以计算商品的总高度,并在onPreferenceChange
中将商品count
加1(直到totalHeight
达到maxHeight
)。
这是完整的实现:
PreferenceKey
来获取视图高度:struct ViewHeightKey: PreferenceKey {
static var defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value += nextValue()
}
}
struct ViewGeometry: View {
var body: some View {
GeometryReader { geometry in
Color.clear
.preference(key: ViewHeightKey.self, value: geometry.size.height)
}
}
}
TaskRowView
(任意高度):struct TaskRowView: View {
let index: Int
var body: some View {
Text("\(index)")
.padding()
.background(Color.red)
}
}
PreferenceKey
:struct ContentView: View {
@State private var count = 0
@State private var totalHeight: CGFloat = 0
@State private var maxHeightReached = false
let maxHeight: CGFloat = 300
var body: some View {
VStack {
Text("Total height: \(totalHeight)")
VStack {
ForEach(0 ..< count, id: \.self) {
TaskRowView(index: $0)
}
}
.background(ViewGeometry())
.onPreferenceChange(ViewHeightKey.self) {
totalHeight = $0
print(count, totalHeight)
guard !maxHeightReached else { return }
if $0 < maxHeight {
count += 1
} else {
count -= 1
maxHeightReached = true
}
}
}
}
}