Let's_Create
Let's_Create

Reputation: 3623

The text doesn't get wrapped in swift UI

Even After setting the .lineLimit(nil) the text doesn't get wrapped.

var body: some View {
    VStack(alignment: .center) {
        Text("SwiftUI is a modern way to declare user interfaces for any Apple platform. ")
            .font(.title)
            .color(.red)
            .lineLimit(nil)
        Text("Create beautiful, dynamic apps faster than ever before.")
            .font(.system(size: 20))
            .lineLimit(nil)
    }.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10))
}

enter image description here

Upvotes: 143

Views: 88640

Answers (10)

Vladimir Tolstikov
Vladimir Tolstikov

Reputation: 2683

I've just set maxWidth to the outer ContentView — now text wraps. Didn't do anything with Text props.

  var body: some Scene {
    WindowGroup {
      ContentView().frame(maxWidth: 300)
    }
  }

Upvotes: 0

Sharpienero
Sharpienero

Reputation: 3884

After spending a lot of time with an error like this, I can't be 100% certain that this is a lineLimit issue. As of writing this post, the solution I found with more complex views is the following snippet of code to prevent wrapping:

.fixedSize(horizontal: false, vertical: true)

This should prevent the interpreter from collapsing text vertically.

Upvotes: 377

Tiago Peres França
Tiago Peres França

Reputation: 3215

The only answer that kinda worked for me was applying .fixedSize(horizontal: false, vertical: true) on the Text.

I say "kinda" because, by using .fixedSize, SwiftUI will completely ignore the size given by the parent and overflow it. If the parent has a background, the layout is ruined. If the parent has a sibling node, the text is rendered on top of it.

I really believe Apple should give us the option to have the ideal size of a Text be its multiline version instead of the one-line counterpart.

While this doesn't happen, I'm using the following monstrosity, but it works:

struct AdaptiveText: View {
  @State private var height: CGFloat?
  var text: String
  
  private func updateHeight(height: CGFloat) -> some View {
    DispatchQueue.main.async {
      self.height = height
    }
    return Color.clear
  }
  
  var body: some View {
    ZStack {
      Text(text)
        .fixedSize(horizontal: false, vertical: true)
        .background() {
          GeometryReader { geo in
            updateHeight(height: geo.size.height)
          }
        }
        .opacity(0)
      
      Text(text)
    }.frame(width: nil, height: height)
  }
}

Upvotes: 1

J. Doe
J. Doe

Reputation: 13083

I just added

.padding()

to my Text instance and it worked

Upvotes: 0

awolf
awolf

Reputation: 1972

The full solution as of Xcode 11.3 / Swift 5.1 is found across multiple answers here.

The explanation for why this is happening is found in Matteo Pacini's answer: using the predefined .font(.title), .font(.headline), etc. seems to bring the behavior that these Text views will size themselves to always ellipsize rather than wrap. However, simply switching to .body doesn't seem like the best work around.

The best workaround is found in Sharpienero's answer: add .fixedSize(horizontal: false, vertical: true) to your Text view. This tells the Text view to NOT do its custom re-sizing horizontal logic of NOT ellipsizing which causes it to follow the standard rules that we're all use to.

Thanks to both of them!

Upvotes: 50

Ky -
Ky -

Reputation: 32143

For my problem, I had a setup like this:

public var body: some View {
    Form {
        Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
            .font(.title)

        Spacer()
            .fixedSize()

        Text("""
            Integer ut orci odio. Proin cursus ut elit eget rutrum. Nunc ante sem, euismod sed purus sed, tempus elementum elit. Phasellus lobortis at arcu quis porta. Cras accumsan leo eu tempus molestie. Suspendisse vulputate diam ipsum, et tristique lorem porta et. Pellentesque sodales est id arcu luctus venenatis.

            Vestibulum non magna lorem. In tincidunt aliquet nunc, sit amet pharetra neque hendrerit id.

            Cras sed!
            """)

        NativeButton("OK", keyEquivalent: .return) { self.screen = .game }
    }
        .frame(maxWidth: 480)
        .fixedSize()
        .padding()
}

Only the first line of the first `Text` and the first few lines of the second `Text` appear

For some reason, all I had to do was add minWidth: 480, idealWidth: 480 to the frame and everything rendered correctly. I didn't expect this because I already applied .fixedSize(), so I figured one of these three should've been enough.

public var body: some View {
    Form {
        Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
            .font(.title)

        Spacer()
            .fixedSize()

        Text("""
            Integer ut orci odio. Proin cursus ut elit eget rutrum. Nunc ante sem, euismod sed purus sed, tempus elementum elit. Phasellus lobortis at arcu quis porta. Cras accumsan leo eu tempus molestie. Suspendisse vulputate diam ipsum, et tristique lorem porta et. Pellentesque sodales est id arcu luctus venenatis.

            Vestibulum non magna lorem. In tincidunt aliquet nunc, sit amet pharetra neque hendrerit id.

            Cras sed!
            """)

        NativeButton("OK", keyEquivalent: .return) { self.screen = .game }
    }
        .frame(minWidth: 480, idealWidth: 480, maxWidth: 480)
        .fixedSize()
        .padding()
}

All the text appears as intended

Upvotes: 10

P. Ent
P. Ent

Reputation: 1823

I had a situation involving a UIViewRepresentable wrapped UITextField which was presented as:

VStack {
    Text("Long enough to wrap....")
    Spacer().frame(height: 40)
    CustomTextField()
}

The Text stopped wrapping when I added the CustomTextField. Nothing I did to the Text helped. If I removed the Spacer() it wrapped just fine!!

I wound up removing the Spacer and adding a bottom padding to the Text. As far as I can tell, my CustomTextField is just fine and I cannot see why it would affect the SwiftUI layout algorithms.

Upvotes: 1

Akbar Khan
Akbar Khan

Reputation: 2415

SwiftUI

.lineLimit(nil) VS .lineLimit(any number)

VStack(alignment: .leading, spacing: 16.0) {
// Sets the maximum number of lines that text can occupy in the view.

      Text("SwiftUI is a user interface toolkit that lets us design apps in a declarative way. ")
      .font(.title)
      .lineLimit(3)

// But if you don't know about the the text size then Sets nil in the lineLimit.

      Text("SwiftUI is a user interface toolkit that lets us design apps in a declarative way. That's a fancy way of saying that we tell SwiftUI how we want our UI to look and work, and it figures out how to make that happen as the user interacts with it.... ")
       .font(.body)
       .lineLimit(nil)
}.padding(EdgeInsets(top: 0, leading: 8, bottom: 0, trailing: 8))

Upvotes: 4

M Reza
M Reza

Reputation: 19758

Try changing the second Text's lineLimit to a number instead of nil:

VStack(alignment: .leading) {
  Text("SwiftUI is a modern way to declare user interfaces for any Apple platform. ")
    .font(.title)
    .color(.red)
    .lineLimit(nil)
  Text("Create beautiful, dynamic apps faster than ever before.")
    .font(.system(size: 20))
    .lineLimit(2)
 }.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10))

Result:

enter image description here

Upvotes: 32

Matteo Pacini
Matteo Pacini

Reputation: 22856

It looks like the font holds line wrapping attributes.

If you change it to body, then it wraps correctly!

enter image description here

Upvotes: 15

Related Questions