SwiftUI+macOS+Xcode:实现HStack右侧视图在其父视图中居中显示
解决方法
核心问题来自两个子视图高度不统一、容器对齐规则未明确两个原因,按以下步骤修改即可实现居中:
- 统一HStack内两个子视图的高度:你当前左侧Y轴标签固定高度为510,右侧图表固定高度为500,10px的高度差会导致天然垂直偏移,把左侧标签的高度改成和右侧一致的500即可。
- 明确HStack的对齐规则:给HStack加上
alignment: .center参数,确保两个子视图在HStack内部垂直方向居中对齐。 - 补充容器的水平居中规则:给HStack外层加
.frame(maxWidth: .infinity, alignment: .center)修饰符,让HStack顶满父VStack的全部宽度,内部的「Y轴标签+图表」整体在父视图水平居中。
修改后的核心代码如下:
import SwiftUI struct MainView: View { @EnvironmentObject var viewModel : ViewModel var body: some View { VStack (alignment: .center) { let maxYValue = viewModel.data.max { $0.Value < $1.Value }?.Value let minYValue = viewModel.data.max { $0.Value > $1.Value }?.Value let deltaY = maxYValue! - minYValue! let maxYVal = Int(round(maxYValue!)) let minYVal = Int(round(minYValue!)) // 明确HStack的对齐规则为垂直居中 HStack(alignment: .center){ VStack{ Text("\(maxYVal)") Spacer() Text("2") Spacer() Text("3") Spacer() Text("3") Spacer() Text("\(minYVal)") } // 高度改为500和右侧图表统一 .frame(width: 100, height: 500, alignment: .trailing) GeometryReader { geometry in Path { path in for index in viewModel.data.indices { let xPosition = ((geometry.size.width) / (CGFloat(viewModel.data.count - 1))) * CGFloat(index + 0) let yPosition = (1 - (CGFloat(viewModel.data[index].Value - minYValue!)) / CGFloat(deltaY) ) * (geometry.size.height) if index == 0 { path.move(to: CGPoint(x : xPosition, y : yPosition)) } path.addLine(to: CGPoint(x : xPosition, y: yPosition)) } } .stroke(Color.blue, style: StrokeStyle(lineWidth: 2, lineCap: .round, lineJoin: .round)) Path { path in path.move(to: CGPoint(x: 0, y: geometry.size.height)) path.addLine(to: CGPoint(x: 0, y: 0)) path.move(to: CGPoint(x: 0, y: geometry.size.height)) path.addLine(to: CGPoint(x: geometry.size.width, y: geometry.size.height)) }.stroke(Color.black, style: StrokeStyle(lineWidth: 2)) Path { path in for index in 0...3 { path.move(to: CGPoint(x: 0 , y: geometry.size.height * CGFloat(index) / 4)) path.addLine(to: CGPoint(x: geometry.size.width , y: geometry.size.height * CGFloat(index) / 4)) } }.stroke(Color.gray, style: StrokeStyle(lineWidth: 0.5)) } .frame(width: 700, height: 500) } // 让HStack整体在父VStack中水平居中 .frame(maxWidth: .infinity, alignment: .center) } } }
如果需要适配窗口动态尺寸,把右侧图表的固定宽度700改成maxWidth: 700即可,窗口宽度小于700时图表会自动缩放适配。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

