我在scrollview和GeometryReader中遇到一些问题。对于我的用例,我尝试了两种方法。这是我的第一个代码结构:
ScrollView
- VStack
- Image
- GeometryReader
- ForEach
- Text
我正在使用几何读取器来获取VStack的宽度,因为它具有填充,并且我不想具有scrollview的完整宽度。
但是对于GeometryReader,仅ForEach循环中的最后一项显示在UI上。而且GeometryReader的高度很小。参见屏幕截图。
import SwiftUI
struct Item: Identifiable {
var id = UUID().uuidString
var value: String
}
struct ContentView: View {
func items() -> [Item] {
var items = [Item]()
for i in 0..<100 {
items.append(Item(value: "Item #\(i)"))
}
return items
}
var body: some View {
ScrollView {
VStack {
Image(systemName: "circle.fill")
.resizable()
.scaledToFill()
.frame(width: 150, height: 150)
.padding()
.foregroundColor(.green)
GeometryReader { geometry in
ForEach(self.items()) { item in
Text(item.value)
.frame(width: geometry.size.width / CGFloat(2), height: geometry.size.width / CGFloat(2))
.background(Color.red)
}
}
.background(Color.blue)
}
.frame(maxWidth: .infinity)
.padding()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
红色是ForEach循环中的项目。蓝色显示GeometryReader,绿色仅显示图像。
ScrollView
-GeometryReader
- VStack
- Image
- ForEach
-Text
然后,我的ForEach循环中的项目将正确呈现,但无法再滚动。
import SwiftUI
struct Item: Identifiable {
var id = UUID().uuidString
var value: String
}
struct ContentView: View {
func items() -> [Item] {
var items = [Item]()
for i in 0..<100 {
items.append(Item(value: "Item #\(i)"))
}
return items
}
var body: some View {
ScrollView {
GeometryReader { geometry in
VStack {
Image(systemName: "circle.fill")
.resizable()
.scaledToFill()
.frame(width: 150, height: 150)
.padding()
.foregroundColor(.green)
ForEach(self.items()) { item in
Text(item.value)
.frame(width: geometry.size.width / CGFloat(2), height: geometry.size.width / CGFloat(2))
.background(Color.red)
}
}
.frame(maxWidth: .infinity)
}
.padding()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
如何存档以正确显示用户界面。我在这里想念什么吗?我真的很感谢您的帮助。谢谢。
首先,由于您使用的是VStack,这意味着您需要垂直滚动。因此,您需要设置maxHeight属性,而不是maxWidth。
第一种方法是,将for..loop包裹在GeometryReader中,然后再包裹在VStack中。因此,直到构建GeometryReader及其子级之前,SwiftUI才意识到您希望这些项垂直堆叠。因此,一个好的解决方法是将GeometryReader放在scrollView之前的第一个块中,以使其起作用:
import SwiftUI
struct Item: Identifiable {
var id = UUID().uuidString
var value: String
}
struct ContentView: View {
func items() -> [Item] {
var items = [Item]()
for i in 0..<100 {
items.append(Item(value: "Item #\(i)"))
}
return items
}
var body: some View {
GeometryReader { geometry in
ScrollView {
VStack {
Image(systemName: "circle.fill")
.resizable()
.scaledToFill()
.frame(width: 150, height: 150)
.padding()
.foregroundColor(.green)
ForEach(self.items()) { item in
Text(item.value)
.frame(width: geometry.size.width / CGFloat(2), height: geometry.size.width / CGFloat(2))
.background(Color.red)
}
}
.frame(maxHeight: .infinity)
.padding()
}
}
.background(Color.blue)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
第二种方法的问题是,将无限高的VStack包装在不一定具有无限高的GeometryReader中。此外,GeometryReader是一个SwiftUI块,用于从外部块读取尺寸,而不是从其子级获取尺寸。
[一般来说,如果要使用当前正在制作的主要SwiftUI组件的Geometry(或设备屏幕,如果它是全屏组件),则将GeometryReader置于其他组件的父级。否则,您需要将GeometryReader组件作为定义良好的尺寸SwiftUI块的唯一子项。