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
相关产品推荐
相关产品推荐

