SwiftUI:如何在GeometryReader内居中VStack中的内容
TabView内VStack内容无法居中的优化方案
问题描述
实现了一个TabView,通过VStack展示内容,但VStack内的内容始终左对齐,设置VStack(alignment: .center)未生效。目前临时方案是用HStack包裹VStack并添加两侧Spacer,寻求更优实现方式。
问题分析
你的代码中,内层GeometryReader包裹了VStack,但存在两个关键问题:
GeometryReader仅提供父容器尺寸的访问能力,不会自动让子视图居中- VStack默认宽度由子视图(固定宽376的
matchCardView())决定,即便设置alignment: .center,也只是让子视图在VStack自身宽度内居中,而非在整个页面水平范围内居中
优化方案
方案1:给VStack添加全屏宽度约束
保留内层GeometryReader的前提下,给VStack设置maxWidth: .infinity,让VStack占满可用宽度,此时alignment: .center就能让子视图在整个水平范围内居中:
var body: some View { GeometryReader{ proxy in let screenSize = proxy.size ZStack (alignment: .top){ Color(hex: "#E8ECF4") tabHeader(size: screenSize) TabView(selection: $currentTab){ ForEach(sampleTabs) {tab in GeometryReader{ proxy in VStack(alignment: .center){ matchCardView() .frame(width: 376) } .frame(maxWidth: .infinity) // 添加该行让VStack占满宽度 .padding(.top, 60) } .ignoresSafeArea() .offsetX{ value in if currentTab == tab { offset = value - (screenSize.width * CGFloat(indexOf(tab: tab))) } } .tag(tab) } } .tabViewStyle(.page (indexDisplayMode:.never)) } .frame(width: screenSize.width, height: screenSize.height) } }
方案2:移除冗余的内层GeometryReader
观察代码发现内层GeometryReader的proxy并未被实际使用,直接移除后,TabView的页面容器会默认让子视图居中布局,无需额外设置:
var body: some View { GeometryReader{ proxy in let screenSize = proxy.size ZStack (alignment: .top){ Color(hex: "#E8ECF4") tabHeader(size: screenSize) TabView(selection: $currentTab){ ForEach(sampleTabs) {tab in VStack(alignment: .center){ matchCardView() .frame(width: 376) } .padding(.top, 60) .ignoresSafeArea() .offsetX{ value in if currentTab == tab { offset = value - (screenSize.width * CGFloat(indexOf(tab: tab))) } } .tag(tab) } } .tabViewStyle(.page (indexDisplayMode:.never)) } .frame(width: screenSize.width, height: screenSize.height) } }
说明
方案2更简洁,移除冗余的GeometryReader既解决了布局问题,又简化了代码结构;如果后续需要用到内层容器的尺寸,再选择方案1即可。
内容的提问来源于stack exchange,提问作者rameez khan
相关产品推荐
相关产品推荐

