SwiftUI Page样式TabView内容被裁剪,如何保留居中80%宽度同时显示侧边卡片
SwiftUI Page样式TabView内容被裁剪,需实现App Store边到边卡片展示效果
核心需求
- 使用Page样式的TabView展示可滚动、支持吸附定位的卡片,将TabView放在HStack中,两侧加Spacer实现居中,TabView宽度设为HStack的80%
- 希望TabView内容可超出自身边界,实现屏幕边到边的展示效果,同时保留居中和80%宽度的设定,和苹果App Store的实现效果一致

当前实现问题
现有代码已经实现了内容居中、宽度为80%的效果,但超出TabView边界的内容被裁剪,第二张卡片无法像苹果示例那样可见,无法实现屏幕边到边的完整展示。
现有代码
struct CardsView: View { var body: some View { VStack { SectionHeaderView() GeometryReader { geometry in HStack(spacing: 0) { Spacer() Group { TabView { CardView() .tag(0) CardView() .tag(1) CardView() .tag(2) } .frame(width: geometry.size.width * 0.8, height: 150) .tabViewStyle(.page(indexDisplayMode: .never)) } Spacer() } } .frame(height: 150) } .padding(EdgeInsets(top: 8, leading: 0, bottom: 8, trailing: 0)) } } struct CardView: View { var body: some View { Group { Group { VStack { HStack { Text("Testing") Spacer() } Spacer() } } .padding() .background(Color.ui.backgroundCell) .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity) .cornerRadius(kCornerRadiusViews) } .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity) .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)) .tag(0) } }
解决方案
SwiftUI已经提供了对应clipsToBounds = false的修饰符,你只需要给TabView添加.clipped(false)即可取消默认裁剪,让子视图超出父视图边界时仍然可见,修改后的TabView代码如下:
TabView { CardView() .tag(0) CardView() .tag(1) CardView() .tag(2) } .frame(width: geometry.size.width * 0.8, height: 150) .tabViewStyle(.page(indexDisplayMode: .never)) .clipped(false) // 新增这一行即可实现需求
兼容低版本系统方案
.clipped(false)仅支持iOS 16.4+、macOS 13.3+及以上系统,如果你的项目需要兼容更低版本,可选择以下两种方案:
- 用
.mask(nil)替代.clipped(false),多数场景下可以实现同样的取消裁剪效果 - 用
UIViewRepresentable包装UIPageViewController,手动设置其内部view的clipsToBounds = false
内容的提问来源于stack exchange,提问作者Nicholas Bastarache
相关产品推荐
相关产品推荐

