I have 2 HStacks sitting in one VStack as follows:
What I'm trying to achieve is to align the leading of Title 2 and Title 4 with each other. And also Title 1 and Title 3 to each other without using frames. Like the following:
Here is my code using HorizontalAlignment (I have also included the preview for convenience):
import SwiftUI
public struct ContentView: View {
public var body: some View {
VStack(alignment: .centerHorizontalAlignment, spacing: 10) {
HStack(alignment: .top, spacing: 16) {
VStack(alignment: .leading, spacing: 10) {
Text("Title 1")
.font(.body)
.fontWeight(.medium)
Text("123456789")
.font(.body)
.foregroundColor(.black.opacity(0.6))
}
.background(Color.green)
VStack(alignment: .leading, spacing: 10) {
Text("Title 2")
.font(.body)
.fontWeight(.medium)
Text("2 lines\nof text")
.font(.body)
.foregroundColor(.gray)
}
.background(Color.red)
.alignmentGuide(.centerHorizontalAlignment) { $0[HorizontalAlignment.leading] }
}
.padding()
.background(Color.purple)
HStack(alignment: .top, spacing: 16) {
VStack(alignment: .leading, spacing: 10) {
Text("Title 3")
.font(.body)
.fontWeight(.medium)
Text("Aaaaaaaaaa")
.font(.body)
.foregroundColor(.black.opacity(0.6))
Text("Bbbbbbbbbbbbbbbbbbbb")
.font(.body)
.foregroundColor(.black.opacity(0.6))
}
.background(Color.yellow)
VStack(alignment: .leading, spacing: 10) {
Text("Title 4")
.font(.body)
.fontWeight(.medium)
Text("Cccccccccccc")
.font(.body)
.foregroundColor(.black.opacity(0.6))
}
.background(Color.blue)
.alignmentGuide(.centerHorizontalAlignment) { $0[HorizontalAlignment.leading] }
}
.font(.body)
.padding()
.background(Color.gray)
}
.padding()
.frame(alignment: .leading)
.background(Color.cyan)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
extension HorizontalAlignment {
enum CenterHorizontalAlignment: AlignmentID {
static func defaultValue(in d: ViewDimensions) -> CGFloat {
d[HorizontalAlignment.center]
}
}
static let centerHorizontalAlignment = HorizontalAlignment(CenterHorizontalAlignment.self)
}
Would be appreciated if someone can give me some hints or solutions on how to achieve this. I'm using Xcode 13.3.1 and Swift 5.
P.S. The text is fully generic and dynamic. So there is no guarantee that there are always 1 or 2 lines of text here. I would like this solution to be generic enough so it works no matter how long the content is.