我会提出以下起点(最简单的情况......阅读下面的原因)
正如它所看到的,它确实提供了居中的无帧移位和正确对齐的侧面元素,但是......有一个缺点-只有在事先知道这三个文本元素不应该在用户中重叠的情况下,它才会在这种最简单的变体中工作运行。如果是这样(真的有这种情况),那么这种方法就可以了。但是,如果左/右文本可能在运行时增长,则需要更多的计算来通过.frame(maxWidth:)
取决于居中元素的宽度来限制它们的宽度......该变体更复杂,但它是可行的。
var body: some View {
ZStack {
HStack {
Text("Longer side")
Spacer()
Text("One")
}
item2()
}
}
private func item2() -> some View {
Text("CENTER")
.background(Color.yellow)
.border(Color.red)
}
更新:这是一种可能的方法来限制一侧不重叠居中的一侧(包含异步更新,因此应在实时预览或模拟器中进行测试)
所以......如果左边的文本是动态的并且需要剪切尾随符号,那么它可以这样......
它会自动适应设备方向的变化
struct TestHorizontalPinCenter: View {
@State var centerFrame: CGRect = .zero
private let kSpacing: CGFloat = 4.0
var body: some View {
ZStack {
HStack {
Text("Longer side very long text to fit")
.lineLimit(1)
.frame(maxWidth: (centerFrame == .zero ? .infinity : centerFrame.minX - kSpacing), alignment: .leading)
Spacer()
Text("One")
}
item2()
.background(rectReader($centerFrame))
}
}
private func item2() -> some View {
Text("CENTER")
.background(Color.yellow)
.border(Color.red)
}
func rectReader(_ binding: Binding<CGRect>) -> some View {
return GeometryReader { (geometry) -> AnyView in
let rect = geometry.frame(in: .global)
DispatchQueue.main.async {
binding.wrappedValue = rect
}
return AnyView(Rectangle().fill(Color.clear))
}
}
}
而如果需要将左侧换行,则.lineLimit(nil)
需要额外的布局,并且解决方案增长,但想法是一样的。希望这对某人有帮助。