UILabel 的默認行為是它防止孤立詞單獨出現在單獨的行上。即:如果自動換行恰好在最后一行保留 1 個單詞。iOS 將通過從前一行發送一個單詞來防止這種情況發生,在最后一行有兩個單詞。
問題是此功能默認情況下不適用于NSMutableAttributedString. 我該如何啟用它?
樣本:
var string = customField?.title ?? ""
if customField?.required == true {
string = " *"
} else {
string = " (\(getLocalizedString(localizedKey: .optional)))"
}
let style = NSMutableParagraphStyle()
if #available(iOS 14.0, *) {
style.lineBreakStrategy = .standard
}
let att = NSMutableAttributedString(string: string, attributes: [.paragraphStyle: style])
titleLabel.attributedText = att
請記住,我NSMutableAttributedString因其他原因被迫使用。2個標簽對我不起作用。

uj5u.com熱心網友回復:
根據OP的評論...
問題不在于屬性文本,因為“普通”文本也會發生同樣的事情。
在 iOS 11(可能是 10)中,Apple 更改了 UIKit 以防止在 aUILabel換行為兩行 text時出現孤兒。仍然允許使用多于兩行的孤兒:

A在 iOS 11 之前...B是當前...C是當前有超過兩行...
注意這個D例子——我沒有安裝 Xcode 測驗版,但根據我看到的其他評論,在iOS 16中,當文本換行超過兩行時,“無孤兒”規則也將被應用。
所以......解決您的問題的一種方法是在最后一個單詞和星號之間使用“非換行符”字符(而不是純空格)。
這是一個快速測驗:
class WrapTestVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let stackView = UIStackView()
stackView.axis = .vertical
stackView.spacing = 4
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
stackView.widthAnchor.constraint(equalToConstant: 320.0),
])
var noteLabel: UILabel!
var testLabel: UILabel!
let noteFont: UIFont = .systemFont(ofSize: 14.0)
noteLabel = UILabel()
noteLabel.font = noteFont
noteLabel.numberOfLines = 0
noteLabel.text = "Just enough to fit:"
stackView.addArrangedSubview(noteLabel)
testLabel = UILabel()
testLabel.backgroundColor = .yellow
testLabel.numberOfLines = 0
testLabel.attributedText = sampleAttrString(method: 0)
stackView.addArrangedSubview(testLabel)
stackView.setCustomSpacing(20.0, after: testLabel)
noteLabel = UILabel()
noteLabel.font = noteFont
noteLabel.numberOfLines = 0
noteLabel.text = "Using a space char:"
stackView.addArrangedSubview(noteLabel)
testLabel = UILabel()
testLabel.backgroundColor = .yellow
testLabel.numberOfLines = 0
testLabel.attributedText = sampleAttrString(method: 1)
stackView.addArrangedSubview(testLabel)
stackView.setCustomSpacing(20.0, after: testLabel)
noteLabel = UILabel()
noteLabel.font = noteFont
noteLabel.numberOfLines = 0
noteLabel.text = "Using a non-break-space char:"
stackView.addArrangedSubview(noteLabel)
testLabel = UILabel()
testLabel.backgroundColor = .yellow
testLabel.numberOfLines = 0
testLabel.attributedText = sampleAttrString(method: 2)
stackView.addArrangedSubview(testLabel)
stackView.setCustomSpacing(20.0, after: testLabel)
noteLabel = UILabel()
noteLabel.font = noteFont
noteLabel.numberOfLines = 0
noteLabel.text = "Although, iOS 16 may give:"
stackView.addArrangedSubview(noteLabel)
testLabel = UILabel()
testLabel.backgroundColor = .yellow
testLabel.numberOfLines = 0
testLabel.attributedText = sampleAttrString(method: 3)
stackView.addArrangedSubview(testLabel)
stackView.setCustomSpacing(20.0, after: testLabel)
}
func sampleAttrString(method: Int) -> NSMutableAttributedString {
let fontA: UIFont = .systemFont(ofSize: 20.0, weight: .bold)
let attsA: [NSAttributedString.Key : Any] = [
.font: fontA,
.foregroundColor: UIColor.blue,
]
let attsB: [NSAttributedString.Key : Any] = [
.font: fontA,
.foregroundColor: UIColor.red,
]
var partOne = NSMutableAttributedString(string: "If the label has enough text so it wraps to more than two lines, UIKit will allow a last word orphan.", attributes: attsA)
var partTwo: NSAttributedString = NSAttributedString()
switch method {
case 0:
()
case 1:
partTwo = NSAttributedString(string: " *", attributes: attsB)
case 2:
partTwo = NSAttributedString(string: "\u{a0}*", attributes: attsB)
case 3:
partOne = NSMutableAttributedString(string: "If the label has enough text so it wraps to more than two lines, UIKit will allow a last\nword orphan.", attributes: attsA)
partTwo = NSAttributedString(string: "\u{a0}*", attributes: attsB)
default:
()
}
partOne.append(partTwo)
return partOne
}
}
輸出:

所以......您需要使用 iOS 16 進行測驗,如果是這種情況,您可能需要進行版本檢查以確定是添加純空格還是非中斷空格。
uj5u.com熱心網友回復:
從 上的lineBreakStrategy屬性的檔案中UILabel,這有助于控制此行為:
當標簽具有屬性字串值時,系統會忽略
textColor、font、textAlignment、lineBreakMode和lineBreakStrategy屬性。改為在屬性字串中設定NSForegroundColorAttributeName、NSFontAttributeName、alignment、lineBreakMode和屬性。lineBreakStrategy
如果您想使用特定的換行策略,例如.standard(“文本系統使用與標準 UI 標簽相同的換行策略配置。”),您需要通過段落風格:
let style = NSMutableParagraphStyle()
style.lineBreakStrategy = .standard
let text = NSMutableAttributedString(
string: "long title with an asterisk at the end *",
attributes: [.paragraphStyle: style]
)
titleLabel.attributedText = text
根據您的文本,設定段落樣式也可能會有所幫助,allowsDefaultTighteningForTruncation因為這可能允許文本系統收緊字串最后一行的單詞之間的空間以使所有內容都適合。(我說可能是因為此屬性專門控制截斷,但文本系統也有可能將其考慮到換行。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/497953.html
標籤:IOS 迅速 代码 nsmutableattributedstring
