Append/prepend HStack 中的一个项目,同时保留其原始中心
Append/prepend an item in an HStack while retaining its original center
我目前有一个居中对齐的简单 VStack:
VStack {
Image(systemName: "arrow.down")
.foregroundColor(.red)
Text("AAA")
}
(注意红色箭头如何与标签的中心完美对齐。)
现在我想向文本行添加另一个项目(例如使用 HStack),但“AAA”仍位于容器的中心:
VStack {
Image(systemName: "arrow.down")
.foregroundColor(.green)
HStack {
Image(systemName: "star")
Text("AAA")
}
}
问题是它不再居中(箭头未对齐的事实证明了这一点):
尝试 1:对齐参考线
我试图通过创建自定义对齐指南来解决此问题:
extension HorizontalAlignment {
struct CustomAlignment: AlignmentID {
static func defaultValue(in context: ViewDimensions) -> CGFloat {
return context[HorizontalAlignment.center]
}
}
static let custom = HorizontalAlignment(CustomAlignment.self)
}
VStack(alignment: .custom) {
Image(systemName: "arrow.down")
.foregroundColor(.blue)
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
HStack {
Image(systemName: "star")
Text("AAA")
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
}
}
尽管箭头现在已正确对齐,但它移动了箭头而不是将箭头保持在原处并移动了 HStack:
(注意在这张图片中,虽然蓝色箭头与“AAA”对齐,但它不再位于中心(即与其他箭头对齐)。)
尝试 #2:对齐参考线 + 偏移
我可以通过硬编码偏移来临时解决这个问题:
VStack(alignment: .custom) {
Image(systemName: "arrow.down")
.foregroundColor(.yellow)
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
HStack {
Image(systemName: "star")
Text("AAA")
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
}
}.offset(x: -15)
现在看起来是正确的:
问题是我需要硬编码这个 -15 值,使用偏移量并不理想。
尝试 #3:隐藏视图
另一种解决方法是在末尾添加一个相同大小的隐藏视图。
VStack {
Image(systemName: "arrow.down")
.foregroundColor(.purple)
HStack {
Image(systemName: "star")
Text("AAA")
Image(systemName: "star")
.opacity(0)
}
}
我宁愿避免使用隐藏视图的解决方案。它还使 HStack 比实际需要的更大。
有没有其他方法可以使“AAA”与屏幕中心对齐,但在其左侧添加星号?
我想避免对任何值进行硬编码,因为标签或图像可能有一天会发生变化。
struct ContentView: View {
@State private var offset: CGFloat = .zero
var body: some View {
VStack {
Image(systemName: "arrow.down")
.foregroundColor(.green)
HStack(spacing: 0) {
Image(systemName: "star")
.overlay(
GeometryReader { geo in
Color.clear.onAppear {
offset = geo.size.width
}
}
)
Text("AAA")
}
.offset(x: -offset/2)
}
}
}
解决此问题的一种方法(也许是最简单的方法)是使用您的自定义对齐指南,并使向下箭头图像占据所有可用的水平方向 space。
您可以通过添加 .frame(maxWidth: .infinity)
.
来做到这一点
VStack(alignment: .custom) {
Image(systemName: "arrow.down")
.foregroundColor(.gray)
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
.frame(maxWidth: .infinity) // Add frame here
HStack {
Image(systemName: "star")
Text("AAA")
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
}
这给出了以下输出:
如果您需要使向下箭头图像可调整大小,请确保在使用 maxWidth 设置框架之前根据图像大小设置框架。
Image(systemName: "arrow.down")
.resizable()
.frame(width: 50, height: 50)
.foregroundColor(.gray)
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
.frame(maxWidth: .infinity)
我目前有一个居中对齐的简单 VStack:
VStack {
Image(systemName: "arrow.down")
.foregroundColor(.red)
Text("AAA")
}
(注意红色箭头如何与标签的中心完美对齐。)
现在我想向文本行添加另一个项目(例如使用 HStack),但“AAA”仍位于容器的中心:
VStack {
Image(systemName: "arrow.down")
.foregroundColor(.green)
HStack {
Image(systemName: "star")
Text("AAA")
}
}
问题是它不再居中(箭头未对齐的事实证明了这一点):
尝试 1:对齐参考线
我试图通过创建自定义对齐指南来解决此问题:
extension HorizontalAlignment {
struct CustomAlignment: AlignmentID {
static func defaultValue(in context: ViewDimensions) -> CGFloat {
return context[HorizontalAlignment.center]
}
}
static let custom = HorizontalAlignment(CustomAlignment.self)
}
VStack(alignment: .custom) {
Image(systemName: "arrow.down")
.foregroundColor(.blue)
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
HStack {
Image(systemName: "star")
Text("AAA")
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
}
}
尽管箭头现在已正确对齐,但它移动了箭头而不是将箭头保持在原处并移动了 HStack:
(注意在这张图片中,虽然蓝色箭头与“AAA”对齐,但它不再位于中心(即与其他箭头对齐)。)
尝试 #2:对齐参考线 + 偏移
我可以通过硬编码偏移来临时解决这个问题:
VStack(alignment: .custom) {
Image(systemName: "arrow.down")
.foregroundColor(.yellow)
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
HStack {
Image(systemName: "star")
Text("AAA")
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
}
}.offset(x: -15)
现在看起来是正确的:
问题是我需要硬编码这个 -15 值,使用偏移量并不理想。
尝试 #3:隐藏视图
另一种解决方法是在末尾添加一个相同大小的隐藏视图。
VStack {
Image(systemName: "arrow.down")
.foregroundColor(.purple)
HStack {
Image(systemName: "star")
Text("AAA")
Image(systemName: "star")
.opacity(0)
}
}
我宁愿避免使用隐藏视图的解决方案。它还使 HStack 比实际需要的更大。
有没有其他方法可以使“AAA”与屏幕中心对齐,但在其左侧添加星号?
我想避免对任何值进行硬编码,因为标签或图像可能有一天会发生变化。
struct ContentView: View {
@State private var offset: CGFloat = .zero
var body: some View {
VStack {
Image(systemName: "arrow.down")
.foregroundColor(.green)
HStack(spacing: 0) {
Image(systemName: "star")
.overlay(
GeometryReader { geo in
Color.clear.onAppear {
offset = geo.size.width
}
}
)
Text("AAA")
}
.offset(x: -offset/2)
}
}
}
解决此问题的一种方法(也许是最简单的方法)是使用您的自定义对齐指南,并使向下箭头图像占据所有可用的水平方向 space。
您可以通过添加 .frame(maxWidth: .infinity)
.
VStack(alignment: .custom) {
Image(systemName: "arrow.down")
.foregroundColor(.gray)
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
.frame(maxWidth: .infinity) // Add frame here
HStack {
Image(systemName: "star")
Text("AAA")
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
}
这给出了以下输出:
如果您需要使向下箭头图像可调整大小,请确保在使用 maxWidth 设置框架之前根据图像大小设置框架。
Image(systemName: "arrow.down")
.resizable()
.frame(width: 50, height: 50)
.foregroundColor(.gray)
.alignmentGuide(.custom, computeValue: { d in d[HorizontalAlignment.center] })
.frame(maxWidth: .infinity)