SwiftUI ScrollView内LazyHStack嵌套的TabView内容隐藏无法显示问题求解
问题原因
- iOS 15及以上版本对
ScrollView嵌套懒加载容器、PageTabViewStyle样式TabView的布局计算逻辑做了变更,原有代码里的LazyHStack未显式指定高度,且TabView的宽度绑定UIScreen.main.bounds在嵌套布局下无法被正确识别,导致布局尺寸计算失效,子项无法渲染。 - 原有代码中
LazyHStack无显式尺寸的前提下保留会触发懒加载容器的自动尺寸协商bug,若业务确实需要嵌套LazyHStack,需要显式指定布局维度避免自适应计算出错。
解决方案
要同时保留垂直滚动能力,可按以下步骤调整:
- 给
ScrollView的内容容器显式指定高度,避免懒加载容器高度计算为0 - 将
TabView的宽度绑定从UIScreen.main.bounds改为外层GeometryReader读取的实际可用宽度,适配横竖屏等不同布局场景 - 若业务不需要
LazyHStack的懒加载横向布局能力可直接移除,若必须保留则给LazyHStack也显式指定和TabView一致的宽高
修正后可运行代码
#if DEBUG struct MyTestView_Previews: PreviewProvider { static var previews: some View { MyTestView() } } #endif struct MyTestView: View { @State var selectedTab: Int = 0 var body: some View { GeometryReader { geometry in VStack(spacing: 0) { ScrollView { // 若业务必须保留LazyHStack则显式指定宽高,高度可根据实际业务需求调整 LazyHStack { TabView(selection: $selectedTab) { ForEach(0...3, id: \.self) { i in Text(String(i)) .frame(maxWidth: .infinity, maxHeight: .infinity) } } .animation(.easeInOut, value: selectedTab) // iOS15+动画需要绑定value避免非预期触发 .frame(width: geometry.size.width, height: 300) // 显式指定TabView宽高 .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) } .frame(width: geometry.size.width, height: 300) // 给LazyHStack指定和TabView一致的宽高 } .frame(height: 300) // ScrollView高度可根据业务调整,若内部垂直滚动内容更多可改设最小高度 Spacer().frame(height: geometry.safeAreaInsets.bottom) } .navigationBarTitle("Test") .edgesIgnoringSafeArea(.bottom) } } }
补充说明
- 如果不需要
LazyHStack的横向懒加载能力,直接删除LazyHStack层即可,代码会更简洁,布局也更稳定 - 尽量不要用
UIScreen.main.bounds来获取布局尺寸,嵌套场景下容易出现适配错误,优先用GeometryReader读取当前父容器的可用尺寸
内容的提问来源于stack exchange,提问作者Niklas
相关产品推荐
相关产品推荐

