SwiftUI TabView设置indexDisplayMode:.never后视图消失问题求助
解决TabView隐藏指示器后下方视图不显示的问题
问题根源
你通过readSize获取子视图尺寸来设置TabView的frame(height: size.height),但设置indexDisplayMode: .never后,TabView的整体布局逻辑发生变化,基于子视图尺寸的frame约束出现计算偏差,导致下方视图被遮挡或挤压。
可行解决方案
方案1:移除固定高度约束,让TabView自适应布局
直接去掉.frame(height: size.height),TabView会根据子视图和自身布局自动计算高度,同时隐藏指示器:
TabView(selection: $selection) { ForEach(0..<5, id: \.self) { index in OnboardingItemView() .tag(index) } } .animation(.easeInOut, value: selection) .transition(.slide) .tabViewStyle(.page(indexDisplayMode: .never)) // 隐藏指示器
方案2:用GeometryReader获取父容器尺寸设置TabView高度
如果必须固定TabView高度,通过GeometryReader获取可用空间,避免依赖子视图的尺寸回调:
GeometryReader { geo in TabView(selection: $selection) { ForEach(0..<5, id: \.self) { index in OnboardingItemView() .tag(index) } } .frame(height: geo.size.height) // 使用父容器高度 .animation(.easeInOut, value: selection) .transition(.slide) .tabViewStyle(.page(indexDisplayMode: .never)) }
方案3:优化readSize的使用逻辑(仍需依赖子视图尺寸时)
给size设置合理初始值,确保布局稳定后再应用frame:
@State private var size: CGSize = .zero var body: some View { TabView(selection: $selection) { ForEach(0..<5, id: \.self) { index in OnboardingItemView() .tag(index) .readSize { newSize in DispatchQueue.main.async { self.size = newSize } } } } .frame(height: size.height == 0 ? UIScreen.main.bounds.height : size.height) // 提供默认高度 .animation(.easeInOut, value: selection) .transition(.slide) .tabViewStyle(.page(indexDisplayMode: .never)) }
关键提示
使用.page风格的TabView时,indexDisplayMode会影响TabView的内在高度计算,手动固定子视图高度容易引发布局冲突,优先选择自适应布局方案。
内容的提问来源于stack exchange,提问作者Ufuk Köşker
相关产品推荐
相关产品推荐

