使用 SwiftUI 模拟 CSS flex-wrap 行为
Posted
技术标签:
【中文标题】使用 SwiftUI 模拟 CSS flex-wrap 行为【英文标题】:emulating CSS flex-wrap behavior with SwiftUI 【发布时间】:2020-09-14 17:01:41 【问题描述】:我正在编写一个 SwiftUI 应用程序,并且想要一个容器视图,它可以将其子项“推入”一行,并且一旦该行填满,就开始将后续子项包装到下一行——换句话说,一个模拟容器视图CSS flexbox 的 flex-wrap: wrap
属性的行为。孩子们具有可变的动态宽度,但高度相同(尽管我怀疑大多数非疯狂的解决方案对可变高度具有鲁棒性)。孩子的数量也是动态的。
toplevel,我的问题是:最简单的方法是什么?如果我需要使用 UIKit 或 obj-c 领域,就这样吧,但我更喜欢独立的解决方案(即,不是 pod Yoga
)。
(注意:我是 ios 开发新手,但熟悉 React 和所有新奇的 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。我得到了包装行为,但不是“flex”行为,至少根据我的阅读,这是.adaptive
声称在锡上做的事情。
所以我的第二个问题是:我对自适应LazyVGrid
对其子项执行大小建议并协商其“自适应列”的大小的方式有什么误解?有没有办法用网格做我想做的事情,如果没有,为什么不(还有什么更好的计划)?
【问题讨论】:
【参考方案1】:编辑:意识到我专注于包装而不是您问题的弹性部分,并且不认为这是您所追求的。
我觉得你只需要设置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)
【讨论】:
【参考方案2】:我对@987654322@ 的理解不正确——它的列总是均匀分布; maximum
参数只允许这些列扩展(同步),以便它们共同填充父级的空间。我认为每一列都可以单独从最小宽度扩展到最大宽度。
一位朋友纠正了我并将我链接到基于HStack
的解决方案:SwiftUI HStack with Wrap
(我之所以留下这个问题,是因为我找到了最好的Lazy*Grid
文章,上面链接,我认为在这一点上可以双向解释,因此我的错误。)
【讨论】:
以上是关于使用 SwiftUI 模拟 CSS flex-wrap 行为的主要内容,如果未能解决你的问题,请参考以下文章