问题描述
我正在编写一个SwiftUI应用,并且想要一个容器视图,该视图将其子级“推送”到一行中,一旦该行填满,便开始将后续子级包装到后续行中,换句话说,就是一个模仿CSS flexBox的flex-wrap: wrap
属性的行为。子级具有可变的动态宽度,但是高度相同(尽管我怀疑大多数非疯狂的解决方案对于可变高度都是健壮的)。孩子的数量也是动态的。
最上层,我的问题是:最简单的方法是什么?如果我需要深入UIKit或obj-c领域,就可以了,但是我更喜欢独立的解决方案(即不是pod Yoga
)。
(注意:我是iOS开发人员的新手,但是熟悉React和所有〜newfangled CSS布局。)
到目前为止,我最好的线索是iOS 14附带的LazyVGrid
视图,特别是在我看来,没有最大值(默认为无穷大)的单个自适应GridItem应该可以解决问题……但是它没有,或者至少我还没有弄清楚如何。 (我发现的*Grid
的最佳参考斜杠详细参考是:https://swiftui-lab.com/impossible-grids/)
我最初尝试这样做:
let columns = [
GridItem(.adaptive(minimum: 42),alignment: .leading)
]
沿着
LazyVGrid(columns: columns,spacing: 10) {
Text("Hello,world!")
.fixedSize(horizontal: true,vertical: false)
.border(Color.gray)
Text("lol")
.fixedSize(horizontal: true,vertical: false)
.border(Color.gray)
Text("bananananananananana")
.fixedSize(horizontal: true,vertical: false)
.border(Color.gray)
}
but that didn't work。设置一个很大的最大值(50000)也无济于事。我在这里的理解是LazyVGrid
应该允许其子级扩展其网格单元格,但这显然不是这里发生的事情。
我想确保这不是Text
害羞而温柔,并拒绝表达其尺寸偏好,所以我尝试使用框架更加明确:
LazyVGrid(columns: columns,spacing: 10) {
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.frame(minWidth: 100,maxWidth: 100)
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
}
but this also doesn't work。我得到了包装行为,但没有“弯曲”行为,至少从我的阅读看来,.adaptive
声称是在锡罐上进行的。
所以我的第二个问题是:我对自适应LazyVGrid
对其子代执行大小建议并协商其“自适应列”的大小的方式有什么误解?有没有办法用网格来做我想要的事情,如果没有,为什么不这样做(还有什么更好的计划)?
解决方法
编辑:意识到我专注于包装而不是问题的弹性部分,并且不认为这是您追求的目标。
我认为您只需要设置alignment属性,即可获得与CSS flexbox的flex-wrap: wrap
shown at CSS tricks.相同的效果。
这似乎对我有用,只有对您的代码所做的更改是在LazyVGrid初始化程序中设置alignment: .leading
。 Result with alignment: .leading
struct ContentView: View {
let columns = [
GridItem(.adaptive(minimum: 42),alignment: .leading)
]
var body: some View {
LazyVGrid(columns: columns,alignment: .leading,spacing: 10) {
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
Text("sup")
.border(Color.gray)
}
}
}
,
我对.adaptive
的理解是不正确的-它的列总是 等距; maximum
参数仅允许这些列扩展(以步进方式),以便它们共同填充父级的空间。我以为每列可以分别从最小宽度扩展到最大宽度。
一个朋友纠正了我,并给我链接了一个基于HStack
的解决方案:SwiftUI HStack with Wrap
(我将这个问题搁置一旁,因为我发现上面链接的最佳Lazy*Grid
文章,我认为在这点上可以同时解释为两种方式,因此是我的错误。)