问题描述
在Swift UI中,尝试通过LazyVGrid实现图片的网格布局,但实际上显示的是列表布局:
List(savePhotos) {img in
LazyVGrid(columns: columns) {
ZStack {
if let photoData = img.photo,let photo = UIImage(data: photoData) {
Image(uiImage: photo)
.resizable()
.scaledToFill()
.frame(width: 80,height: 80)
.clipped()
}
}
.cornerRadius(10)
}
}
因为图片使用CoreData,因此通过List遍历存储的图片,再通过LazyVGrid展示 3 * 3 的布局:
@Query var savePhotos: [Photo]
let columns = [
GridItem(.fixed(80)), // 自动根据屏幕宽度生成尽可能多的单元格,宽度最小为 80 点
GridItem(.fixed(80)),
GridItem(.fixed(80))
]
LazyVGrid的效果并没有实现出现。
问题原因
1、List 的限制
SwiftUI 的 List 是为垂直滚动设计的,它将其子视图(包括 LazyVGrid)布局为一个列表项。即使定义了网格列,它仍会按照列表项来布局。
2、网格没有单独的容器
LazyVGrid 应该直接放在一个适当的容器(如 ScrollView 或 VStack)中,而不是嵌套在 List 中。
解决方法
1、使用 ScrollView 替代 List
ScrollView 支持任意方向的滚动,适合用来承载 LazyVGrid。
ScrollView {
LazyVGrid(columns: columns, spacing: 10) {
ForEach(savePhotos) { img in
if let photoData = img.photo, let photo = UIImage(data: photoData) {
Image(uiImage: photo)
.resizable()
.scaledToFit()
.frame(width: 80, height: 80) // 设置每张图片的大小
.cornerRadius(8)
}
}
}
.padding()
}
2、完全依赖网格布局
如果所有内容都是图片展示,直接用 LazyVGrid。
LazyVGrid(columns: columns, spacing: 10) {
ForEach(savePhotos) { img in
if let photoData = img.photo, let photo = UIImage(data: photoData) {
Image(uiImage: photo)
.resizable()
.scaledToFill()
.frame(width: 80, height: 80)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
}
}
.padding()
通过LazyVGrid和ForEach配合能够实现3*3网格布局的效果。
注意事项
1、frame 限制
在 LazyVGrid 中为每个子视图设置 frame(width:height:),确保布局一致且符合列的宽度定义。
2、spacing 调整
可以为 LazyVGrid 设置 spacing 参数,定义行间和列间的间距。
3、布局适配
如果希望网格宽度自动适配屏幕,可以用 .adaptive 替代 .fixed。
let columns = [GridItem(.adaptive(minimum: 80))]