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

SwiftUI中如何让LazyVGrid的Grid Item实现动态高度?

SwiftUI实现动态高度的笔记网格布局

你的核心需求是让笔记Item根据内容自适应高度,同时消除列内空隙,实现类似瀑布流的布局。原生LazyVGrid默认按行布局,每行高度由该行最高Item决定,因此会产生空隙,下面提供两种解决方案:

方案一:双列LazyVStack实现瀑布流(推荐)

这种方式完全匹配你的期望效果,左右列各自独立排列,Item高度完全由内容决定,列内无空隙:

完整代码

import SwiftUI

// 假设你的Note模型定义如下
struct Note: Identifiable {
    let id = UUID()
    let title: String
    let description: String
}

struct NotesView: View {
    let notesArray: [Note]
    
    // 将数据源均分至左右两列
    private var leftColumnNotes: [Note] {
        notesArray.enumerated().filter { $0.offset % 2 == 0 }.map { $0.element }
    }
    
    private var rightColumnNotes: [Note] {
        notesArray.enumerated().filter { $0.offset % 2 != 0 }.map { $0.element }
    }
    
    var body: some View {
        ScrollView {
            HStack(spacing: 16) { // 列之间的间距
                LazyVStack(spacing: 16) { // 左列内部Item间距
                    ForEach(leftColumnNotes) { note in
                        NoteCard(note: note)
                    }
                }
                
                LazyVStack(spacing: 16) { // 右列内部Item间距
                    ForEach(rightColumnNotes) { note in
                        NoteCard(note: note)
                    }
                }
            }
            .padding(.horizontal)
        }
    }
}

// 提取笔记卡片为独立View,提升复用性
struct NoteCard: View {
    let note: Note
    
    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text(note.title)
                .font(.poppinsSemiBold(size: 12))
            Text(note.description)
                .font(.poppinsRegular(size: 10))
                .foregroundStyle(.gray)
        }
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 5)
                .foregroundStyle(.white)
        )
        .frame(maxWidth: .infinity, alignment: .top) // 卡片占满列宽,顶部对齐
        // 移除固定高度限制,让内容自动撑开高度
    }
}

方案二:优化LazyVGrid(仅顶部对齐,行高仍统一)

如果可以接受同一行高度由最高Item决定,仅需要Item顶部对齐而非被拉伸,可以修改GridItem的对齐方式:

let columns = [
    GridItem(.flexible(), alignment: .top),
    GridItem(.flexible(), alignment: .top)
]

var body: some View {
    ScrollView {
        LazyVGrid(columns: columns, spacing: 16, content: {
            ForEach(notesArray) { note in
                NoteCard(note: note)
            }
        })
        .padding(.horizontal)
    }
}

方案对比

  • 方案一:完全实现你想要的效果,列内Item无空隙,高度完全自适应
  • 方案二:保留网格布局逻辑,同一行高度统一,仅解决Item顶部对齐问题,仍会存在行内空隙

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 06:25:09