I want to produce a bubble-like view with various pieces of text on a rounded rectangle background, sized to fit the text. I have arrived at this:
var body: some View {
HStack {
Spacer()
ZStack(alignment: .trailing) {
Color.blue
VStack{
Text(message.content)
.padding(.all, .oneUnit)
.multilineTextAlignment(.trailing)
}
}
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
When that is repeated with a ForEach
and some text passed in as message, content is almost right but the ZStack
background should only be big enough to cover the text, making a bubble:
Using .layoutPriority
fixes this, code becomes:
var body: some View {
HStack {
Spacer()
ZStack(alignment: .trailing) {
Color.blue
VStack{
Text(message.content)
.padding(.all, .oneUnit)
.multilineTextAlignment(.trailing)
}
.layoutPriority(1)
}
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
So the size of the ZStack
is the size required to fit the text. Great! Now to put all the required pieces of text in the VStack
. Let's add one more Text
:
var body: some View {
HStack {
Spacer()
ZStack(alignment: .trailing) {
Color.blue
VStack{
Text(message.content)
.padding(.all, .oneUnit)
.multilineTextAlignment(.trailing)
Text("Out damned spot!")
}
.layoutPriority(1)
}
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
Text display underneath, sizing still correct.
But that last piece of text has to be right-aligned. So then the code is:
var body: some View {
HStack {
Spacer()
ZStack(alignment: .trailing) {
Color.blue
VStack{
Text(message.content)
.padding(.all, .oneUnit)
.multilineTextAlignment(.trailing)
HStack {
Spacer()
Text("Out damned spot!")
}
}
.layoutPriority(1)
}
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
And then everything is broken. Can anyone say why the HStack
breaks the ZStack
's size?
CodePudding user response:
@SwissMark is right, the cause of your problem is that Spacer()
is greedy, it takes all the space left. Making your bubbles the max size possible. But only making VStack
alignment .trailing
doesn't do the trick.
Problems:
- Your background is Set in the
ZStack
- layoutPriority doesn't make any sense here
Here is the solution:
import SwiftUI
struct ContentView: View {
var messages = [
"I heard the owl scream and the crickets cry.",
"Out damned spot!",
"Did not you speak?",
"Out damned spot!",
"When?",
"Out damned spot!",
"Now.",
"Out damned spot!"
]
var body: some View {
HStack {
Spacer()
ZStack(alignment: .trailing) {
VStack(alignment: .trailing) {
VStack(alignment: .trailing) {
Text(messages[0])
.padding(.all, 4)
.multilineTextAlignment(.trailing)
Text(messages[1])
.padding([.bottom, .trailing], 4)
}
.padding(4)
.background(Color.blue)
.clipShape(RoundedRectangle(cornerRadius: 12))
VStack(alignment: .trailing) {
Text(messages[2])
.padding(.all, 4)
.multilineTextAlignment(.trailing)
Text(messages[3])
.padding([.bottom, .trailing], 4)
}
.padding(4)
.background(Color.blue)
.clipShape(RoundedRectangle(cornerRadius: 12))
VStack(alignment: .trailing) {
Text(messages[4])
.padding(.all, 4)
.multilineTextAlignment(.trailing)
Text(messages[5])
.padding([.bottom, .trailing], 4)
}
.padding(4)
.background(Color.blue)
.clipShape(RoundedRectangle(cornerRadius: 12))
VStack(alignment: .trailing) {
Text(messages[6])
.padding(.all, 4)
.multilineTextAlignment(.trailing)
Text(messages[7])
.padding([.bottom, .trailing], 4)
}
.padding(4)
.background(Color.blue)
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
}
}
}
Final image:
Modify the paddings and spaces as you wish.