Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI Text won't expand into multiple lines

I've just started using SwiftUI with the retail build. I cannot get one of my text views to automatically expand into multiple lines. I've read many thread on SO and HackingWithSwift but cannot get it to work. I think perhaps it might be tied to my other frames but I'm not sure where to start

struct Message: View {
    var body: some View {
        ZStack() {
            Color.blue.cornerRadius(8)
            VStack(alignment: .leading, spacing: 8) {
                Text("Lorem Ipsum")
                    .foregroundColor(.white)
                    .bold()
                    .font(.system(size: 20))
                Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Donec enim diam vulputate ut pharetra. Sed turpis tincidunt id aliquet risus feugiat in. Interdum velit laoreet id donec ultrices tincidunt arcu non.  Lorem END")
                    .foregroundColor(.white)
                    .lineLimit(nil)
                Text("Sent to Group1 by iShaymus")
                    .foregroundColor(.white)
                    .italic()
                    .opacity(0.5)
                    .font(.system(size: 12))
            }
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
            .padding(12)
        }
    }
}

I've tried applying frames to the Text(). I've tried adding .font(.body). I've tried setting .lineLimit(100). None of them worked. The output is always as follows:

iOS Screenshot

The entire body string is noticeably longer:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Donec enim diam vulputate ut pharetra. Sed turpis tincidunt id aliquet risus feugiat in. Interdum velit laoreet id donec ultrices tincidunt arcu non.  Lorem END

This is the working code thanks to Marc

import SwiftUI

struct Message: View {

    @State var title = ""
    @State var messageBody = ""
    @State var sentBy = ""
    @State var targetSite = ""

    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text(title)
                .foregroundColor(.white)
                .bold()
                .font(.system(size: 20))
            Text(messageBody)
                .foregroundColor(.white)
                .fixedSize(horizontal: false, vertical: true)
            Text("Sent to \(targetSite) by \(sentBy)")
                .foregroundColor(.white)
                .italic()
                .opacity(0.5)
                .font(.system(size: 12))
            }
            .frame(minWidth: 0, maxWidth: .infinity, alignment: .topLeading)
            .padding(12)
            .background(Color.blue)
            .cornerRadius(10)
    }
}
like image 948
iShaymus Avatar asked Sep 21 '19 23:09

iShaymus


2 Answers

I think this is what you are looking for. Use .fixedSize(horizontal: false, vertical: true) as required.

struct Message: View {
    var body: some View {
        ZStack() {
            Color.blue.cornerRadius(8)
            VStack(alignment: .leading, spacing: 8) {
                Text("Lorem Ipsum")
                    .foregroundColor(.white)
                    .bold()
                    .font(.system(size: 20))
                Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Donec enim diam vulputate ut pharetra. Sed turpis tincidunt id aliquet risus feugiat in. Interdum velit laoreet id donec ultrices tincidunt arcu non.  Lorem END")
                    .foregroundColor(.white)
                      .fixedSize(horizontal: false, vertical: true)
                Text("Sent to Group1 by iShaymus")
                    .foregroundColor(.white)
                    .italic()
                    .opacity(0.5)
                    .font(.system(size: 12))
            }
         //   .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
            .padding(12)
        }
          .fixedSize(horizontal: false, vertical: true)
    }
}
like image 185
Marc T. Avatar answered Sep 22 '22 14:09

Marc T.


Your code doesn't match your screenshot so I can't test this exactly but I think what you want here is the layout priority modifier (.layoutPriority(1)).

Use this modifier to give priority to spacing when the views are being laid out.

Example

(Excerpt from "SwiftUI Views" Book) Excerpt from SwiftUI Views Book

Code

Take a look at the comments in this code:

struct LayoutPriority_Intro: View {
    var body: some View {
        VStack(spacing: 20) {
            Text("Layout Priority").font(.largeTitle)
            Text("Introduction").foregroundColor(.gray)
            Text("Use layout priority to tell the parent which child views get priority when it comes to assigning layout space.")
                .layoutPriority(1) // Second highest priority
                .frame(maxWidth: .infinity)
                .padding()
                .background(Color.yellow)
                .foregroundColor(.black)
            
            Text("No layout priority (default is 0)")
            VStack(alignment: .leading, spacing: 8) {
                HStack {
                    Image("profile2").mask(Circle())
                    Text("Janice Okoro").font(.largeTitle)
                }
                Text("Lorem ipsum dolor amet laborum gastropub laboris magna.")
                    .font(.body)
            }
            .padding()
            .foregroundColor(.black)
            .background(Color.yellow.cornerRadius(8))
            .padding(.horizontal)
            
            Text("Layout priority used")
            VStack(alignment: .leading, spacing: 8) {
                HStack {
                    Image("profile2").mask(Circle())
                    Text("Janice Okoro").font(.largeTitle)
                }
                Text("Lorem ipsum dolor amet laborum gastropub laboris magna.")
                    .font(.body)
            }
                // Give this view spacing priority over the other child views
                .layoutPriority(2) // Highest priority
                .padding()
                .foregroundColor(.black)
                .background(Color.yellow.cornerRadius(8))
                .padding(.horizontal)
        }
        .font(.title)
        .edgesIgnoringSafeArea(.bottom)
    }
}

When I look at your code example it looks fine, but I'm suspecting if you replace .lineLimit(nil) (which you don't need) with .layoutPriority(1) then it might fix your issue.

If that doesn't help, put the layout priority on your VStack.

like image 27
Mark Moeykens Avatar answered Sep 26 '22 14:09

Mark Moeykens