SwiftUI使用InsetGroupedListStyle时List行高仅滚动后才正常如何解决
问题原因
这是SwiftUI自iOS14推出InsetGroupedListStyle以来就存在的已知Bug,根源是List底层依赖的UITableView首次渲染时,对动态高度的多行文本高度估算错误,只有滚动触发单元格重用时才会重新计算得到正确高度。该问题和文本类型无关,只要是可能换行的长文本都可能触发,且官方直到iOS15版本仍未彻底修复,iOS16及以上系统该问题出现概率大幅降低。
可行解决方案
按实现成本从低到高排序:
方案1:优化Text的布局修饰符
删除.fixedSize(horizontal: false, vertical: true),改为显式声明文本的换行规则和布局范围:
Text("https://example.govt.nz/notice/id/2021-go1593") .lineLimit(nil) // 显式声明不限制行数 .frame(maxWidth: .infinity, alignment: .leading) // 占满行可用宽度,避免横向压缩 .id(文本内容变量) // 文本内容变化时强制重绘,高度重新计算
80%以上的场景用这个方案就能解决。
方案2:调整UITableView全局估算高度配置
因为SwiftUI的List底层是UITableView,可以通过修改全局UIAppearance配置修正估算逻辑:
struct ContentView: View { init() { // 设为接近你业务场景的平均行高,减少估算误差 UITableView.appearance().estimatedRowHeight = 60 UITableView.appearance().rowHeight = UITableView.automaticDimension } // 原有视图代码 }
注意该配置会全局生效,如果你项目里其他地方的List有自定义行高需求,需要单独适配。
方案3:用ScrollView+LazyVStack替代List
如果前两个方案都不能完全覆盖你的场景,可以直接绕开UITableView的历史包袱,用原生SwiftUI布局实现和InsetGroupedListStyle完全一致的效果:
import SwiftUI struct ContentView: View { var body: some View { ScrollView { LazyVStack(spacing: 20, pinnedViews: .sectionHeaders) { Section(header: Text("Header Title") .font(.subheadline) .foregroundColor(.secondary) .frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal, 20) .padding(.bottom, 8) ) { Text("https://example.govt.nz/notice/id/2021-go1593") .lineLimit(nil) .frame(maxWidth: .infinity, alignment: .leading) .padding() .background(Color(UIColor.systemBackground)) .cornerRadius(10) .padding(.horizontal, 16) } // 其他Section } .padding(.vertical) } .background(Color(UIColor.systemGroupedBackground)) } }
该方案完全不会出现高度计算错误的问题,性能和系统List基本一致,还支持更灵活的样式自定义。
内容的提问来源于stack exchange,提问作者alionthego
相关产品推荐
相关产品推荐

