|
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)
|
|
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.
|
|
Just wondering if anyone has made any progress here ...
|
|
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.
|
|
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)
}
}
}
|
|
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
|
|
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.
|