SwiftUI多LazyVGrid旋转时滚动异常问题求助
SwiftUI LazyVGrid旋转屏幕卡顿、单元格不复用空白问题解决
问题现象
使用上述SwiftUI代码时,上下滚动功能正常,但旋转屏幕时出现卡顿,旧单元格无法复用,屏幕出现大片空白,仅回滚操作能恢复正常显示。
问题根源
- 列配置错误:
ThreeGridLarge中定义了3个.adaptive类型的GridItem,但.adaptive本身会根据父容器宽度自动生成满足minimum要求的列数,手动添加多个.adaptive会导致布局计算逻辑混乱,旋转时列数重新计算出错。 - 单元格高度不确定性:
BasicCell中的Spacer()会让单元格高度依赖父容器,LazyVGrid无法提前确定单元格尺寸,导致旋转时复用机制失效。 - 多网格布局冲突:多个独立的
LazyVGrid嵌套在同一个ScrollView中,旋转时多个网格同时重新计算布局,加重渲染负担引发卡顿。
修复方案
1. 修正列配置
将ThreeGridLarge中的columns改为单个.adaptive的GridItem,让系统自动管理列数:
var columns: [GridItem] { [GridItem(.adaptive(minimum: 217), spacing: 24, alignment: .leading)] }
2. 移除单元格内的Spacer
删除BasicCell中的Spacer(),让单元格高度由内部内容决定,确保LazyVGrid能准确计算尺寸:
struct BasicCell: View { let item: Item var body: some View { VStack(alignment: .leading, spacing: 0) { Color(.gray) .cornerRadius(4) .aspectRatio(CGSize(width: 361, height: 217), contentMode: .fit) Text(item.title) .padding(.top, 12) .foregroundColor(.red) Text(item.description) .padding(.top, 8) Text(item.teaser) .fixedSize(horizontal: false, vertical: true) .padding(.top, 10) // 移除Spacer() } } }
3. 优化多网格布局(可选)
如果需要保留多个网格模块,可以给每个ThreeGridLarge添加明确的垂直间距,或者将所有items合并到一个LazyVGrid中,通过分区来区分模块,减少布局计算的复杂度:
// 合并为单个LazyVGrid的示例 struct GridView: View { // 合并所有items let allItems: [Item] = [ Item(title: "GEMEENTERAADSVERKIEZINGEN", description: "Diefstal, bedreiging, geruïneerde zakenpartners: de twee gezichten van ondernemer Willem Blijdorp", teaser: "Willem Blijdorp is een mediaschuwe, maar gevierde ondernemer die geroemd wordt om zijn successen. Geruïneerde ex-zakenpartners vertellen een ander verhaal. „Ik voel me zakelijk vermoord door Blijdorp.”"), Item(title: "MEDIA", description: "Rechter verbiedt uitzending EenVandaag", teaser: "De zitting vond achter gesloten deuren plaats. Zowel de orde van advocaten als EenVandaag mogen geen mededelingen doen over de inhoud van de zaak."), Item(title: "ZWARE MISHANDELING", description: "Lil Kleine opnieuw vast na beroep OM tegen vrijlating", teaser: "Rapper Lil Kleine wordt verdacht van zware mishandeling. Hij kwam twee weken geleden vrij. Het OM zag voldoende „ernstige bezwaren” om hem langer vast te houden en in dat oordeel ging de rechtbank vandaag mee."), Item(title: "GEMEENTERAADSVERKIEZINGEN", description: "Diefstal, bedreiging, geruïneerde zakenpartners: de twee gezichten van ondernemer Willem Blijdorp", teaser: "Willem Blijdorp is een mediaschuwe, maar gevierde ondernemer die geroemd wordt om zijn successen. Geruïneerde ex-zakenpartners vertellen een ander verhaal. „Ik voel me zakelijk vermoord door Blijdorp.”"), Item(title: "MEDIA", description: "Rechter verbiedt uitzending EenVandaag", teaser: "De zitting vond achter gesloten deuren plaats. Zowel de orde van advocaten als EenVandaag mogen geen mededelingen doen over de inhoud van de zaak."), Item(title: "ZWARE MISHANDELING", description: "Lil Kleine opnieuw vast na beroep OM tegen vrijlating", teaser: "Rapper Lil Kleine wordt verdacht van zware mishandeling. Hij kwam twee weken geleden vrij. Het OM zag voldoende „ernstige bezwaren” om hem langer vast te houden en in dat oordeel ging de rechtbank vandaag mee.") ] var columns: [GridItem] { [GridItem(.adaptive(minimum: 217), spacing: 24, alignment: .leading)] } var body: some View { ScrollView { LazyVGrid(columns: columns, alignment: .leading, spacing: 16) { // 第一组 Section { ForEach(allItems.prefix(3)) { item in BasicCell(item: item) } } .padding(.top, 45) // 第二组 Section { ForEach(allItems.suffix(3)) { item in BasicCell(item: item) } } .padding(.top, 45) } .padding(.horizontal, 24) } } }
验证效果
修改后旋转屏幕,LazyVGrid能正确复用单元格,布局计算顺畅,不会出现空白和卡顿问题。
内容的提问来源于stack exchange,提问作者Jason Giorgio Meulenhoff
相关产品推荐
相关产品推荐

