问题
The problem coming even in storyboard.
The UILabel is having following properties:
- numberOfLines = 0
- lineBreakMode = .byWordWrapping
- Constraints: Leading & Trailing 26 points to superview; vertically center.
- Custom Font: Medium 17 Points.
As you can see the fourth word cannot fit in the first line and hence a problem by creating bad layout. If I remove the last word the sentence fits in one line completely or say the fourth word. If adding a word after it moves both of them to next line which leaves a lot of space. It should try to fit words without breaking or hyphenation as much as possible in one line. But clearly empty space is made even when word can fit.
You can recreate this in a new project and observe the issue.
回答1:
You may want to give this a try...
Subclass UITextView
, disable scrolling, editing and selecting... set the textContainerInset = UIEdgeInsets.zero
and textContainer.lineFragmentPadding = 0
to Zero.
Result:
Code (@IBDesignable
so we can see it in IB / Storyboard):
@IBDesignable
class TextViewLabel: UITextView {
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() -> Void {
isScrollEnabled = false
isEditable = false
isSelectable = false
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
}
}
回答2:
This code can be used in fixed width label and it will overcome that, also can get the height of the label
private static func calculateLabelProperties() -> (String, CGFloat){
let titleString = "Your string here"
let wordArray = titleString.components(separatedBy: " ")
var lineCount = 1//first line denoted by 1
var tempWidth:CGFloat = 0
var title = ""
for (index,element) in wordArray.enumerated() {
let width = calculateFontSize(title: element + " ", fontName: "your font name", fontSize: 17).width
tempWidth = tempWidth + width
//get the nextelement
var nextElement = ""
if wordArray.count > index + 1 {
nextElement = wordArray[index + 1]
}
let nextElementWidth = calculateFontSize(title: nextElement, fontName: "your font name", fontSize: 17).width
if tempWidth + nextElementWidth > 410 {//410 is labelwidth
tempWidth = 0
lineCount += 1
title = "\(title)\(element)\n"
} else {
title = "\(title)\(element) "
}
}
return (title, CGFloat(lineCount * 20))//20 is label sigle line height
}
this code calculate font size
func calculateFontSize(title: String, fontName: String, fontSize: CGFloat) -> (width: CGFloat, height: CGFloat){
let font = UIFont(name: fontName, size: fontSize)
return (title.size(OfFont: font!).width, title.size(OfFont: font!).height)
}
get font size
extension String {
func size(OfFont font: UIFont) -> CGSize {
return (self as NSString).size(withAttributes: [NSAttributedString.Key.font: font])
}
}
来源:https://stackoverflow.com/questions/56869332/uilabel-word-wrap-feature-leaving-space-even-when-sufficient-space-available-for