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 RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

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.