强制 UILabel 不使用连字符
Force UILabel to not hyphen words
所以我在 UIView 中有一个普通的 UILabel,里面有一些文字。这是一个 3 行标签,具有 .adjustsFontSizeToFitWidth = true
大多数情况下它工作正常,但在某些情况下会出现单词连字符,如下所示:
但在其他字母组合中,它就像我 want/need,它没有连字符,只是调整大小:
我需要的是强制 UILabel 不要 break/hyphen 个单词,而是更喜欢调整大小。换行模式在这里作用不大。
有没有一种方法我想念关闭连字符或中断这个词?
我也试图找出如何检查单词是否被打断但也找不到它,所以我可以调整行数。
编辑:这里是 playground 代码,可以看看:
import Foundation
import UIKit
import PlaygroundSupport
public class Card: UIView {
var label2: UILabel!
public init(frame: CGRect, withText: String) {
super.init(frame: frame)
self.backgroundColor = UIColor(red: 0.313, green: 0.89, blue: 0.76, alpha: 1.000)
label2 = UILabel(frame: CGRect(x: bounds.width / 2 - 115, y: (bounds.height/2 - 90), width: 230, height: 180))
label2.textAlignment = .center
label2.text = "stepper; rotory; revolutionizing"
label2.font = UIFont.boldSystemFont(ofSize: 60)
label2.textColor = UIColor.white
label2.adjustsFontSizeToFitWidth = true
label2.translatesAutoresizingMaskIntoConstraints = false
label2.numberOfLines = 0
self.addSubview(label2)
// label2.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
// label2.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -50).isActive = true
// label2.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 50).isActive = true
// label2.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
let card = Card(frame: CGRect(x: 10, y: 30, width: 280, height: 200), withText: "")
let page = PlaygroundPage.current
let view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 500))
view.backgroundColor = UIColor.white
view.addSubview(card)
page.liveView = view
有两种方法,第一种是:
yourLabel.text = "stepper;\nrotor;\nrevolutioning;"
只需在任何单词的最后添加 \n...
第二个:
创建 3 个带有相关文本的标签,并将其放入垂直 stackView 中...
let yourLabel1 = UILabel()
let yourLabel2 = UILabel()
let yourLabel3 = UILabel()
yourLabel1.text = "stepper;"
yourLabel2.text = "rotor;"
yourLabel3.text = "revolutioning;"
之后创建堆栈视图并添加标签
let stackView = UIStackView(arrangedSubviews: [label1, label2, label3])
stackView.axis = .vertical
stackView.distribution = .fillEqually
... etc etc
设置 stackView 约束,一切顺利
更新您的评论:
yourLabel.text = "stepper; rotor; revolutioning; xxxxxxx; xx; xxxxxxxxxxxxxx; xxxxx; xxxxxxxxxxxx"
yourLabel.font = .systemFont(ofSize: 40, weight: .semibold)
yourLabel.textColor = .black
yourLabel.adjustsFontSizeToFitWidth = true;
yourLabel.minimumScaleFactor = 0.2;
yourLabel.numberOfLines = 0;
yourLabel.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(yourLabel)
yourLabel.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
yourLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50).isActive = true
yourLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50).isActive = true
yourLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
具体更新
添加此扩展名:
extension UILabel{
func adjustedFont()->UIFont {
let attributes: [NSAttributedString.Key: Any] = [.font: font as Any]
let attributedString = NSAttributedString(string: text ?? "", attributes: attributes)
let drawingContext = NSStringDrawingContext()
drawingContext.minimumScaleFactor = minimumScaleFactor
attributedString.boundingRect(with: bounds.integral.size, options: .usesLineFragmentOrigin, context: drawingContext)
let fontSize = font.pointSize * drawingContext.actualScaleFactor
return font.withSize(fontSize)
}
func fitLabelWords(){
layoutIfNeeded()
let scaledFont = self.adjustedFont()
let currentFont = scaledFont
if let txt = text,
let maxString = txt.components(separatedBy: " ").max(by: {.count > [=14=].count})?.replacingOccurrences(of: "\n", with: ""){
let maxFontSize: CGFloat = currentFont.pointSize
let minFontSize: CGFloat = 5.0
var maxS = maxFontSize
var minS = minFontSize
let height = currentFont.lineHeight
let constraintSize = CGSize(width: .greatestFiniteMagnitude, height: height)
var sizedFont = currentFont
while(minS <= maxS){
let currentSize = (minS + maxS) / CGFloat(2)
sizedFont = currentFont.withSize( CGFloat(currentSize) )
let text = NSMutableAttributedString(string:maxString, attributes:[NSAttributedString.Key.font:sizedFont])
let textRect = text.boundingRect(with: constraintSize, options: [.usesLineFragmentOrigin], context: nil).integral
let labelSize = textRect.width
//1 is a fudge factor
if labelSize == ceil(self.bounds.width - 1){
break
}else if labelSize > ceil(self.bounds.width - 1){
maxS = currentSize - 0.1
}else{
minS = currentSize + 0.1
}
}
if sizedFont.pointSize < currentFont.pointSize{
self.font = sizedFont
}
}
}
}
像这样设置标签:
label2 = UILabel(frame: CGRect(x: view.bounds.width / 2 - 115, y: (view.bounds.height/2 - 90), width: 230, height: 180))
label2.textAlignment = .center
label2.text = "stepper; rotory; revolutionizing; skfghjkadsghasdg;"
label2.numberOfLines = 0
label2.font = UIFont.boldSystemFont(ofSize: 60)
label2.textColor = .white
label2.adjustsFontSizeToFitWidth = true
label2.minimumScaleFactor = 0.3
label2.fitLabelWords()
view.addSubview(label2)
所以我在 UIView 中有一个普通的 UILabel,里面有一些文字。这是一个 3 行标签,具有 .adjustsFontSizeToFitWidth = true
大多数情况下它工作正常,但在某些情况下会出现单词连字符,如下所示:
但在其他字母组合中,它就像我 want/need,它没有连字符,只是调整大小:
我需要的是强制 UILabel 不要 break/hyphen 个单词,而是更喜欢调整大小。换行模式在这里作用不大。 有没有一种方法我想念关闭连字符或中断这个词? 我也试图找出如何检查单词是否被打断但也找不到它,所以我可以调整行数。
编辑:这里是 playground 代码,可以看看:
import Foundation
import UIKit
import PlaygroundSupport
public class Card: UIView {
var label2: UILabel!
public init(frame: CGRect, withText: String) {
super.init(frame: frame)
self.backgroundColor = UIColor(red: 0.313, green: 0.89, blue: 0.76, alpha: 1.000)
label2 = UILabel(frame: CGRect(x: bounds.width / 2 - 115, y: (bounds.height/2 - 90), width: 230, height: 180))
label2.textAlignment = .center
label2.text = "stepper; rotory; revolutionizing"
label2.font = UIFont.boldSystemFont(ofSize: 60)
label2.textColor = UIColor.white
label2.adjustsFontSizeToFitWidth = true
label2.translatesAutoresizingMaskIntoConstraints = false
label2.numberOfLines = 0
self.addSubview(label2)
// label2.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
// label2.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -50).isActive = true
// label2.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 50).isActive = true
// label2.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
let card = Card(frame: CGRect(x: 10, y: 30, width: 280, height: 200), withText: "")
let page = PlaygroundPage.current
let view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 500))
view.backgroundColor = UIColor.white
view.addSubview(card)
page.liveView = view
有两种方法,第一种是:
yourLabel.text = "stepper;\nrotor;\nrevolutioning;"
只需在任何单词的最后添加 \n...
第二个: 创建 3 个带有相关文本的标签,并将其放入垂直 stackView 中...
let yourLabel1 = UILabel()
let yourLabel2 = UILabel()
let yourLabel3 = UILabel()
yourLabel1.text = "stepper;"
yourLabel2.text = "rotor;"
yourLabel3.text = "revolutioning;"
之后创建堆栈视图并添加标签
let stackView = UIStackView(arrangedSubviews: [label1, label2, label3])
stackView.axis = .vertical
stackView.distribution = .fillEqually
... etc etc
设置 stackView 约束,一切顺利
更新您的评论:
yourLabel.text = "stepper; rotor; revolutioning; xxxxxxx; xx; xxxxxxxxxxxxxx; xxxxx; xxxxxxxxxxxx"
yourLabel.font = .systemFont(ofSize: 40, weight: .semibold)
yourLabel.textColor = .black
yourLabel.adjustsFontSizeToFitWidth = true;
yourLabel.minimumScaleFactor = 0.2;
yourLabel.numberOfLines = 0;
yourLabel.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(yourLabel)
yourLabel.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
yourLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50).isActive = true
yourLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50).isActive = true
yourLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
具体更新 添加此扩展名:
extension UILabel{
func adjustedFont()->UIFont {
let attributes: [NSAttributedString.Key: Any] = [.font: font as Any]
let attributedString = NSAttributedString(string: text ?? "", attributes: attributes)
let drawingContext = NSStringDrawingContext()
drawingContext.minimumScaleFactor = minimumScaleFactor
attributedString.boundingRect(with: bounds.integral.size, options: .usesLineFragmentOrigin, context: drawingContext)
let fontSize = font.pointSize * drawingContext.actualScaleFactor
return font.withSize(fontSize)
}
func fitLabelWords(){
layoutIfNeeded()
let scaledFont = self.adjustedFont()
let currentFont = scaledFont
if let txt = text,
let maxString = txt.components(separatedBy: " ").max(by: {.count > [=14=].count})?.replacingOccurrences(of: "\n", with: ""){
let maxFontSize: CGFloat = currentFont.pointSize
let minFontSize: CGFloat = 5.0
var maxS = maxFontSize
var minS = minFontSize
let height = currentFont.lineHeight
let constraintSize = CGSize(width: .greatestFiniteMagnitude, height: height)
var sizedFont = currentFont
while(minS <= maxS){
let currentSize = (minS + maxS) / CGFloat(2)
sizedFont = currentFont.withSize( CGFloat(currentSize) )
let text = NSMutableAttributedString(string:maxString, attributes:[NSAttributedString.Key.font:sizedFont])
let textRect = text.boundingRect(with: constraintSize, options: [.usesLineFragmentOrigin], context: nil).integral
let labelSize = textRect.width
//1 is a fudge factor
if labelSize == ceil(self.bounds.width - 1){
break
}else if labelSize > ceil(self.bounds.width - 1){
maxS = currentSize - 0.1
}else{
minS = currentSize + 0.1
}
}
if sizedFont.pointSize < currentFont.pointSize{
self.font = sizedFont
}
}
}
}
像这样设置标签:
label2 = UILabel(frame: CGRect(x: view.bounds.width / 2 - 115, y: (view.bounds.height/2 - 90), width: 230, height: 180))
label2.textAlignment = .center
label2.text = "stepper; rotory; revolutionizing; skfghjkadsghasdg;"
label2.numberOfLines = 0
label2.font = UIFont.boldSystemFont(ofSize: 60)
label2.textColor = .white
label2.adjustsFontSizeToFitWidth = true
label2.minimumScaleFactor = 0.3
label2.fitLabelWords()
view.addSubview(label2)