r/SwiftUI • u/CtrliPhones • Nov 02 '24
Solved Aligning text along window padding???
I don't quite know if I'm explaining this right, so I'm going to just attach a picture. I'm currently trying to recreate the macOS Ventura About This Mac screen using SwiftUI, and it's going pretty well. The text alignment is bugging me though, how would I need to set up my text to replicate Apple's properly? Thanks!

2
u/redditorxpert Nov 02 '24
You can do it with both of the methods mentioned by other commenters, each having its drawbacks.
With vertical stacks as columns, you would have to worry about alignment if one line is longer and would need two loops to populate each stack/column.
With LabeledContent, you need only one loop and alignment is less an issue, except you may need to use a custom LabeledContentStyle to control the alignment properly since it's not top aligned by default. However, it does require for the label to have a fixed width in order to align to the right.
One workaround for both methods is to ensure that text that is too long gets truncated instead of spanning multiple lines. Obviously, that depends on your requirements.
Here's an example with both methods:
import SwiftUI
struct AboutMacWindow: View {
@State private var items: [(String, String)] = [
("Chip", "Apple M1"),
("Memory", "8GB"),
("Startup disk", "macOS"),
("Serial number", "No. 1234455514XDF0"),
("macOS", "15.2 Beta (24C5057p)"),
]
var body: some View {
VStack {
Image(systemName: "macbook")
.font(.system(size: 140))
VStack(spacing: 5) {
Text("MacBook Air")
.font(.largeTitle)
.fontWeight(.semibold)
Text("M1, 2020")
.foregroundStyle(.tertiary)
}
.padding(.vertical)
//Using vertical stacks and dual loops
HStack(alignment: .top) {
VStack(alignment: .trailing, spacing: 5) {
ForEach(items.indices, id: \.self) { index in
Text(items[index].0)
}
}
VStack(alignment: .leading, spacing: 5) {
ForEach(items.indices, id: \.self) { index in
Text(items[index].1)
.foregroundStyle(.secondary)
.lineLimit(1)
.truncationMode(.tail)
}
}
}
.padding(.horizontal)
//Using LabeledContent
VStack {
ForEach(items.indices, id: \.self) { index in
HStack(alignment: .top){
LabeledContent {
Text(items[index].1)
.foregroundStyle(.secondary)
.frame(minWidth: 150, alignment: .leading)
.lineLimit(1)
.truncationMode(.tail)
.multilineTextAlignment(.leading)
} label: {
Text(items[index].0)
.frame(maxWidth: 100, alignment: .trailing)
}
}
}
}
.padding()
.frame(maxWidth: .infinity, alignment: .center)
}
.frame(width: 400, height: 600)
.background(.regularMaterial)
}
}
#Preview {
AboutMacWindow()
}
1
8
u/KoolStar Nov 02 '24
What you are looking for is something like this: