54

Since List doesn't look like its configurable to remove the row dividers at the moment, I'm using a ScrollView with a VStack inside it to create a vertical layout of text elements. Example below:

ScrollView {
    VStack {
        // ...
        Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer mattis ullamcorper tortor, nec finibus sapien imperdiet non. Duis tristique eros eget ex consectetur laoreet.")
            .lineLimit(0)
    }.frame(width: UIScreen.main.bounds.width)
}

The resulting Text rendered is truncated single-line. Outside of a ScrollView it renders as multi-line. How would I achieve this inside a ScrollView other than explicitly setting a height for the Text frame ?

George Ananda Eman
  • 3,292
  • 8
  • 28
  • 29

5 Answers5

115

In Xcode 11 GM:

For any Text view in a stack nested in a scrollview, use the .fixedSize(horizontal: false, vertical: true) workaround:

ScrollView {
    VStack {
        Text(someString)
            .fixedSize(horizontal: false, vertical: true)
    }
}

This also works if there are multiple multiline texts:

ScrollView {
    VStack {
        Text(someString)
            .fixedSize(horizontal: false, vertical: true)
        Text(anotherLongString)
            .fixedSize(horizontal: false, vertical: true)
    }
}

If the contents of your stack are dynamic, the same solution works:

ScrollView {
    VStack {
        // Place a single empty / "" at the top of your stack.
        // It will consume no vertical space.
        Text("")
            .fixedSize(horizontal: false, vertical: true)

        ForEach(someArray) { someString in
            Text(someString)
              .fixedSize(horizontal: false, vertical: true)
        }
    }
}
Andre Carrera
  • 2,606
  • 2
  • 12
  • 15
  • The error doesn't throw in Preview right? Because in preview it did show the same truncation behaviour as before.. but without the `Spacer()`it worked just fine.. – thisIsTheFoxe Jul 17 '19 at 12:40
  • Awesome! I was using geometry reader.. but too much for too less – Fernando Martínez Jul 28 '19 at 10:59
  • As of beta 5, `.infinity` crashes for me, but `.frame(idealHeight: .greatestFiniteMagnitude)` works. – dalton_c Aug 01 '19 at 12:33
  • 2
    I have many dynamically generated views inside of a scrollview, some of them containing Text several layers down their respective view tree. Unfortunately, none of these solutions work -- I still see a bunch of Text fields compressed into a single line. Has anyone experienced a similar issue? I'm on the GM release of Xcode – neptune Sep 12 '19 at 19:54
  • 1
    Why does this work? it would almost make more sense to have the true and false the other way round, as the vertical height should be flexible and not fixed. – Jonathan. Sep 10 '21 at 10:04
7

You can force views to fill their ideal size, for example in a vertical ScrollView:

ScrollView {
    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer mattis ullamcorper tortor, nec finibus sapien imperdiet non. Duis tristique eros eget ex consectetur laoreet.")
        .fixedSize(horizontal: false, vertical: true)
}

Feels a little better to me than modifying the frame.

kyis
  • 181
  • 4
  • 4
3

It seems like there is bug in SwiftUI. For now you have to specify height for your VStack container

ScrollView {
      VStack {
           // ...
               Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer mattis ullamcorper tortor, nec finibus sapien imperdiet non. Duis tristique eros eget ex consectetur laoreet.")
                    .lineLimit(nil)
            }.frame(width: UIScreen.main.bounds.width, height: 500)
       }
apphud
  • 625
  • 4
  • 8
3

The following works for me with Beta 3 - no spacer, no width constraint, flexible height constraint :

ScrollView {
    VStack {
        Text(longText)
            .lineLimit(nil)
            .font(.largeTitle)
            .frame(idealHeight: .infinity)
    }
}
blackjacx
  • 9,011
  • 7
  • 45
  • 56
1

The correct solution is to just make sure to set the alignment for your stack:

VStack(alignment: .leading)

ScrollView {
    VStack(alignment: .leading) {
        // ...
        Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer mattis ullamcorper tortor, nec finibus sapien imperdiet non. Duis tristique eros eget ex consectetur laoreet.")
            .lineLimit(0)
    }.frame(width: UIScreen.main.bounds.width)
}

This way you don't need the fixedSize as the layout is properly defined.

Alexandru Motoc
  • 582
  • 7
  • 14