Home > OS >  Prevent Text with background from expanding to maxWidth
Prevent Text with background from expanding to maxWidth

Time:02-04

I have a Text with a background (which is just a coloured bubble), and I'm trying to restrict its maxWidth to some width, say 200 for this example.

I'm running into a problem with .frame(..., maxWidth: ...).

Expected Behvaiour

enter image description here

  • smaller messages are as big as they need to be
  • larger messages will have a width up to the maxWidth and will wrap without text being truncated

Actual Behaviour

  • no matter in which order the .background() and .frame() modifiers are applied, the Text is always drawn as what I have set the maxWidth to be.

In more detail: Applying the .background() before the .frame(maxWidth: 200):

Text(...)
    .fixedSize(horizontal: false, vertical: true)
    .background(
        Rectangle()               
    )
                    
    .frame(maxWidth: 200)

enter image description here

This results in the frame of all the Texts being of width 200 - which I'm not understanding. I understand that the background is applied before, so the background size is correct, but why does the frame become the maximum width? Am I misunderstanding how the maxWidth: frame works?

This behaviour is the exact same without the .fixedSize() modifier, as all that does is prevent the text from truncating into ...

Applying the .background() after the .frame(maxWidth: 200):

Text(...)
    .fixedSize(horizontal: false, vertical: true)
    .frame(maxWidth: 200)

    .background(
        Rectangle()               
    )

enter image description here

This shows the behaviour again, but this time with the background also affected by the frame. The modifier stacking behaviour is expected, but again, I'm not sure why the Text is expanding to the maxWidth.

For further information, these Texts are within an HStack with a Spacer() on the left side. The HStacks are within a larger VStack ScrollView. Removing the HStack, Spacer() or the ScrollView/VStack does not change this behaviour.

I have tried giving it a minWidth and applying other modifiers to no avail. Any help is appreciated, as I feel that I'm missing something very obvious!

Thanks.

Edit: greater concision.

CodePudding user response:

You should apply .frame(maxWidth:) to the VStack, not to each Text.

struct TestView: View {
    
    var body: some View {
        VStack {
            HStack {
                MyText(text: "111")
                MyText(text: "111")
            }
            MyText(text: "222222222")
            MyText(text: "3333333333333")
            MyText(text: "Long long long long long long long long long long text")
        }
        .frame(maxWidth: 200) // << there
    }
    
    struct MyText: View {
        var text: String
        
        var body: some View {
            Text(text)
                .padding(6)
                .background(
                    Rectangle()
                        .fill(.yellow)
                )
                .border(.blue)
        }
    }
}

The blue border represents the actual Text frame sizes. Preview

If you need a trailing alignment, then you should to set it in VStack(alignment: .trailing). Preview2

If you also need a trailing alignment inside Text frame, you can apply .multilineTextAlignment(.trailing) to Text.

  • Related