I have two Text()
s in SwiftUI. One is a long multi-line text, left aligned. The other is a short one line text, right aligned. I'd like to arrange the two in the following way.
The code below renders the second screenshot, but it can't put the second text on the same line if there is space like in the first screenshot.
struct TextTest: View {
var body: some View {
VStack(alignment: .trailing){
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sa laborum.")
Text("(c) 2024")
.font(.caption)
}
.padding()
Spacer()
}
}
Is there a way to handle both cases automatically in SwiftUI? Maybe using the new TextRenderer API?
Two things that don't work:
Text("a")+Text("b")
) as the second text will not be right aligned.You can determine the footprint needed for showing the two texts by concatenating them together and showing as hidden. Then, show the visible versions as overlays, using .topLeading
alignment for the main text and .trailingLastTextBaseline
for the copyright.
struct TextTest: View {
let text: String
let copyright = "(c) 2024"
var body: some View {
(Text(text) + Text(copyright))
.hidden()
.overlay(alignment: .topLeading) {
Text(text)
}
.overlay(alignment: .trailingLastTextBaseline) {
Text(copyright)
.font(.caption)
}
.padding()
}
}
Example cases:
let loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sa laborum."
let shortText = "The quick brown fox"
var body: some View {
VStack(spacing: 20) {
TextTest(text: loremIpsum)
TextTest(text: shortText)
}
}
The concatenated form is sized using a single font for the combined text. If the copyright message is shown in a smaller font then it will need less space, which means there is sure to be a gap between the main text and the copyright message (as can be seen in the second example). The edge case would be, where the copyright message doesn't fit in the normal font but does fit in the smaller font. If this is an issue then you could use a few less characters for the copyright message when building the concatenated form.