You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免LazyVGrid单元格中的图片被挤压变形?

SwiftUI网格单元格图片避免挤压的优化方案

我做了一个简单的网格视图,每个单元格内显示一张方形图片,下方附带几行文字。目标是让图片完全填充方形区域,只做裁剪处理,绝对不能出现挤压变形的情况。目前效果接近预期,但图片还是会出现挤压问题:

(注:原问题附带图片显示部分单元格图片被横向挤压变形)

初始实现代码

struct CollectionsView: View {
    @StateObject var viewModel: CollectionsViewModel = CollectionsViewModel()
    var body: some View {
        ScrollView {
            let columns = [GridItem(spacing: 16), GridItem(spacing: 16)]
            LazyVGrid(columns: columns) {
                ForEach(viewModel.collections) { collection in
                    Button {
                        print("进入合集页面")
                    } label: {
                        CollectionsViewCell(collection: collection)
                    }
                    .onAppear {
                        if collection == viewModel.collections.last {
                            Task {
                                try await viewModel.getCollections(nextPage: true)
                            }
                        }
                    }
                }
            }
            .padding(16)
        }
        .navigationTitle("合集")
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                Button {
                    // 更多按钮点击事件
                } label: {
                    Image(systemName: "ellipsis.circle")
                }
            }
        }
    }
}

struct CollectionsViewCell: View {
    let collection: HashableCollection
    var body: some View {
        VStack(alignment: .leading) {
            AsyncImage(url: URL(string: collection.imageUrlString)) { image in
                image
                    .resizable()
                    .aspectRatio(1, contentMode: .fill)
            } placeholder: {
                Rectangle()
            }
            .background(.secondary)
            .clipped()
            .cornerRadius(11)
            Text(collection.title)
                .lineLimit(1)
                .truncationMode(.tail)
            Text("\(collection.itemCount) 个项目\(collection.itemCount == 1 ? "" : "s")")
                .foregroundColor(.secondary)
        }
    }
}

我尝试过使用Geometry Reader,但它在ScrollView中的表现不佳——有没有更优的实现方法?

自行尝试的解决方案(感觉过于繁琐)

struct CollectionsView: View {
    @StateObject var viewModel: CollectionsViewModel = CollectionsViewModel()
    var body: some View {
        GeometryReader { geometry in
            ScrollView {
                let spacing: Double = 16
                let columns = [GridItem(spacing: spacing), GridItem(spacing: spacing)]
                LazyVGrid(columns: columns) {
                    ForEach(viewModel.collections) { collection in
                        Button {
                            print("进入合集页面")
                        } label: {
                            let geometryInfo = GeometryInfo(size: geometry.size, columnCount: Double(columns.count), spacing: spacing)
                            CollectionsViewCell(geometryInfo: geometryInfo, collection: collection)
                        }
                        .onAppear {
                            if collection == viewModel.collections.last {
                                Task {
                                    try await viewModel.getCollections(nextPage: true)
                                }
                            }
                        }
                    }
                }
                .padding(spacing)
            }
            .navigationTitle("合集")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button {
                        // 更多按钮点击事件
                    } label: {
                        Image(systemName: "ellipsis.circle")
                    }
                }
            }
        }
    }
}

struct CollectionsViewCell: View {
    let geometryInfo: GeometryInfo
    let collection: HashableCollection
    var body: some View {
        VStack(alignment: .leading) {
            AsyncImage(url: URL(string: collection.imageUrlString)) { image in
                image
                    .resizable()
                    .scaledToFill()
            } placeholder: {
                Rectangle()
            }
            .frame(width: getImageSize(), height: getImageSize())
            .background(.secondary)
            .clipped()
            .cornerRadius(11)
            Text(collection.title)
                .lineLimit(1)
                .truncationMode(.tail)
            Text("\(collection.itemCount) 个项目\(collection.itemCount == 1 ? "" : "s")")
                .foregroundColor(.secondary)
        }
    }
    func getImageSize() -> Double {
        (geometryInfo.size.width - ((geometryInfo.columnCount + 1) * geometryInfo.spacing)) / geometryInfo.columnCount
    }
}

有没有更简洁的优化方式?


内容的提问来源于stack exchange,提问作者Halpo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 23:45:55