SwiftUI 列表中基于约束的图像布局
Posted
技术标签:
【中文标题】SwiftUI 列表中基于约束的图像布局【英文标题】:Constraint-based layout of images in a list in SwiftUI 【发布时间】:2021-06-03 16:32:24 【问题描述】:我想在SwiftUI
List
中实现以下基于约束的图像布局:
Image
的左/右边缘固定到列表边距(适应屏幕大小)
基于纵横比的动态高度(我也可以使用固定高度)
保持图片纵横比,内容应填满空间
我尝试过但不起作用的方法(基于this article):
struct MyView: View
@ObservedObject var viewModel: MyViewModel
let aspectRatio = CGSize(width: 345, height: 120)
var body: some View
List
ForEach(viewModel.items) item in
GeometryReader geo in
Image("test_image")
.resizable()
.aspectRatio(aspectRatio, contentMode: .fill)
.frame(width: geo.size.width)
.clipped()
我从geo
得到的尺寸在 iPhone 11 Pro 上是 (343, 32)。宽度是有道理的,但由于某种原因,它不会让单元格扩展超过 32 的高度。欢迎任何提示,因为我真的开始怀念自动布局约束了。
【问题讨论】:
【参考方案1】:不需要使用GeometryReader
来处理这样的事情。对于固定高度,您只能提供 frame
和 height
。您也不需要创建自己的 let aspectRatio = CGSize(width: 345, height: 120)
- 如果您将其保留为 nil(默认情况下)应该没问题。
编辑:使用 padding
而不是 VStack
带间距
struct MyView: View
var body: some View
List
ForEach(0..<10, id: \.self) item in
Image("test_image")
.resizable()
.aspectRatio(contentMode: .fill) /// no need for custom aspect ratio
.frame(height: 120) /// fixed height of image
.clipped() /// stop image from overflowing
.padding(.vertical, 12) /// extra vertical padding
结果("test_image"):
但是,它的高度固定为120
,因此图像的顶部和底部都被裁剪掉了。要解决此问题,您可以完全避免使用 frame
和 clipped
。
struct MyView: View
var body: some View
List
ForEach(0..<10, id: \.self) item in
Image("test_image")
.resizable()
.aspectRatio(contentMode: .fill) /// doesn't matter if it's fit or fill
.padding(.vertical, 12) /// extra vertical padding
结果:
【讨论】:
为什么会有VStack 和 List?不应该是要么吗?不过谢谢你,这让我走上了正轨。不回答动态高度问题,但在这一点上这将是一个奖励。 @rmp251 你是对的,它应该是List
或VStack
+ ScrollView
。我只为间距做了 VStack - 我会更新我的答案。
当图像相对于固定高度非常宽时,此解决方案似乎会中断。它不允许宽度受边距限制。但是它适用于“高”图像(例如正方形)。以上是关于SwiftUI 列表中基于约束的图像布局的主要内容,如果未能解决你的问题,请参考以下文章
Swift:将 SwiftUI 元素添加到 UIKit 项目:无法正确应用约束