UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SwiftUI wrapping text mid-word

Forums > SwiftUI

Hello,

I'm working on a SwiftUI project with cards that contain text. However, swiftUI will sometimes cutoff the text mid-word and put a single (or a few) letters on a new line. I want to prevent words from being cutoff mid-line, but can't figure out how to do so.

I would appreciate any thoughts on how to prevent the text from wrapping when I don't want it to.

var body: some View {
        VStack (alignment: .center){
            HStack {
                Spacer()
                VStack {
                    Spacer()
                    Text(card.text.uppercased())
                            .font(.largeTitle)
                            .minimumScaleFactor(0.5)
                            .foregroundColor(Colors.shared.questionText)
                            .multilineTextAlignment(.center)
                            .lineLimit(4)
                            .allowsTightening(true)
                    //.padding(.horizontal, 3)
                    Spacer()
                    Text(card.emojis)
                        .font(.system(size: 54))
                        .minimumScaleFactor(0.5)
                        .multilineTextAlignment(.center)
                        .lineLimit(1)
                        .allowsTightening(true)
                    //.padding(.horizontal, 3)
                    Spacer()
                    Text(card.examples)
                        .minimumScaleFactor(0.5)
                        .foregroundColor(Colors.shared.exampleText)
                        .multilineTextAlignment(.center)
                        .lineLimit(2)
                        .allowsTightening(true)
                    //.padding(.horizontal, 5)
                    Spacer()
                }
                Spacer()

            }
        }
        .padding(.horizontal, 2)
        .background(
            RoundedRectangle(cornerRadius: 15)
                .foregroundColor(Colors.shared.cardBackground)
                .shadow(radius: 2)
        )
        .opacity(1)

3      

I know it's not much help, but if it makes you feel any better at all I can tell you that I, too, have been unsuccessfully dealing with this problem for a year now.

I can't seem to stop Springsteen or Millenium from displaying as Springste / en or Milleni / um on two lines, regardless of how I change the modifiers. It's awful.

3      

Just wondering if anyone has made any progress here ...

3      

@kdeda  

My problem is reverse. On a macOS application SwiftUI.Text insists on wrapping by word instead of char, and it does not use the available width properly. Really frustrating. SwiftUI on the mac feels like beta software.

3      

You could use UIKit's UILabel for that:

struct InnerUILabel: UIViewRepresentable {
    let font: UIFont?
    let color: UIColor
    let lines: Int
    let text: String
    let textAlignment: NSTextAlignment

    @Binding var dynamicHeight: CGFloat

    func makeUIView(context: Context) -> UILabel {
        let lbl = UILabel()
        lbl.text = text
        lbl.font = font
        lbl.textColor = color
        lbl.numberOfLines = lines
        lbl.lineBreakMode = .byWordWrapping
        lbl.textAlignment = textAlignment
        lbl.lineBreakStrategy = .pushOut
        lbl.allowsDefaultTighteningForTruncation = true
        lbl.setContentCompressionResistancePriority(
            .defaultLow,
            for: .horizontal
        )
        lbl.setContentCompressionResistancePriority(
            .defaultLow,
            for: .vertical
        )
        return lbl
    }

    func updateUIView(_ uiView: UILabel, context: Context) {
        DispatchQueue.main.async {
            dynamicHeight = uiView.sizeThatFits(
                CGSize(width: uiView.bounds.width, height: CGFloat.greatestFiniteMagnitude)
            ).height
        }
    }
}

public struct WrappedLabel: View {
    @State private var height: CGFloat = .zero
    let font: UIFont?
    let color: UIColor
    let lines: Int
    let text: String
    let textAlignment: NSTextAlignment
    let redacted: Bool

    public init(
        _ text: String,
        font: UIFont? = .systemFont(ofSize: 15),
        textAlignment: NSTextAlignment = .center,
        color: UIColor = .black,
        redacted: Bool = false,
        lines: Int = 0
    ) {
        self.text = text
        self.textAlignment = textAlignment
        self.font = font
        self.color = color
        self.lines = lines
        self.redacted = redacted
    }

    public var body: some View {
        if redacted {
            Text(text)
                .font(Font(font ?? .systemFont(ofSize: 12)))
                .multilineTextAlignment(textAlignment == .center ? .center : .leading)
                .lineLimit(lines > 0 ? lines : nil)
                .foregroundColor(Color(color))
                .redacted(reason: .placeholder)
        } else {
            InnerUILabel(
                font: font,
                color: color,
                lines: lines,
                text: text,
                textAlignment: textAlignment,
                dynamicHeight: $height
            )
            .frame(minHeight: height)
            .fixedSize(horizontal: false, vertical: true)
        }
    }
}

4      

Hi micartu, yeah cool but what about a little more context. Maybe you got a usage tip too? I already take the code and put it in a swift-File with the UI-imports (SwiftUI and UIKit) ontop thank you and kindly Regards

2      

Here is what I got so far...


// micartu's code in an extra Swift-File with 
// import UIKit   and   import SwiftUI

import SwiftUI

struct ContentView: View {
    private var stringTextVariable: String = "can't seem to stop Springsteen or Millenium, 
                                              can't seem to stop Springsteen or Millenium, 
                                              can't seem to stop Springsteen or Millenium"
    var body: some View {

    VStack(alignment: .leading, spacing: 10) {
        InnerUILabel(font: .boldSystemFont(ofSize: 15), 
                     color: .black, 
                     lines: 2, 
                     text: stringTextVariable, 
                     textAlignment: .justified, 
                     dynamicHeight:  ) // <- down there
    }
  }
}

I think I found how to use it with cmd + "klick-klack" on the appropriate system-Library components. But now I'm struggling with the Binding-Parameter (down there). I don't know what to do there.

2      

Hacking with Swift is sponsored by Superwall

SPONSORED Superwall lets you build & test paywalls without shipping updates. Run experiments, offer sales, segment users, update locked features and more at the click of button. Best part? It's FREE for up to 250 conversions / mo and the Superwall team builds out 100% custom paywalls – free of charge.

Learn More

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.