I'm trying to create a simple fixture list (a list of one team vs another team) in SwiftUI. The "vs" Text
field needs to be centrally aligned on the screen with team1 immediately to the left of this and team2 immediately to the right. A simple example of this is shown in the image below. Note how vs always appears on the centre line and the team names are essentially leading or trailing aligned to the "vs" Text
box...
If the 3 text items are aligned in a simple HStack
, it is the sum width of these text fields which is aligned centrally on the screen and as such the "vs" Text
field will wander from side to side on the screen.
I am confident I could create the desired effect above using geometry reader but this feels like it would be somewhat arduous and I was wondering if there is a simple alignment type or extension that could be used to create the desired effect?
CodePudding user response:
You can make use of alignment guides. This answer also centers the vs
to the screen, not just relative to each other.
Code:
struct ContentView: View {
private let games: [Game] = [
Game("Manchester United", vs: "Arsenal"),
Game("Liverpool", vs: "Newcastle United")
]
var body: some View {
ZStack(alignment: .centerVs) {
Color.clear
.frame(height: 0)
.frame(maxWidth: .infinity)
.alignmentGuide(.centerVs) { d in
d[HorizontalAlignment.center]
}
VStack(alignment: .centerVs) {
ForEach(games) { game in
HStack {
Text(game.team1)
Text("vs")
.alignmentGuide(.centerVs) { d in
d[HorizontalAlignment.center]
}
Text(game.team2)
}
}
}
}
}
}
struct Game: Identifiable {
let id = UUID()
let team1: String
let team2: String
init(_ team1: String, vs team2: String) {
self.team1 = team1
self.team2 = team2
}
}
extension HorizontalAlignment {
private struct CenterVsAlignment: AlignmentID {
static func defaultValue(in context: ViewDimensions) -> CGFloat {
context[HorizontalAlignment.center]
}
}
static let centerVs = HorizontalAlignment(CenterVsAlignment.self)
}
extension Alignment {
static let centerVs = Alignment(horizontal: .centerVs, vertical: .center)
}
Result: