背景:做app经常遇到一段话,不同的内容需要不一样的字体或颜色来显示。这种情况用NSMutableAttributedString,需要的代码量有点多。需求往往是一个部分一个属性,所以用多个部分拼凑来构成NSAttributedString 这样更符合业务逻辑。(灵感来自flutter)
包括两种样式:1.aaBB 的分块样式,2.aaBBaa 的插入式的样式
(情况一: aaBB样式有明确的分块)
1.代码
extension NSMutableAttributedString {
convenienceinit?(elements: [(str :String, attr : [NSAttributedString.Key:Any])]) {
guardelements.count>0else{
returnnil
}
letallString:String= elements.reduce("") { (res, ele) ->Stringin
returnres+ele.str
}
self.init(string: allString)
foreleinelements {
leteleStr = ele.str
letrange:Range= allString.range(of: eleStr)!
letnsRange:NSRange=NSRange(range, in: allString)
self.addAttributes(ele.attr, range: nsRange)
}
}
}
2.使用
let lab = UILabel(frame: CGRect(x: 100, y: 200, width: 300, height: 100))
view.addSubview(lab)
let headStr = "head"
let centerStr = "center"
let backStr = "back"
let attrStr = NSMutableAttributedString(elements: [
(str: headStr, attr: [NSAttributedString.Key.foregroundColor : UIColor.black, NSAttributedString.Key.font
: UIFont.systemFont(ofSize: 14)]),
(str: centerStr, attr: [NSAttributedString.Key.foregroundColor : UIColor.yellow, NSAttributedString.Key.font
: UIFont.systemFont(ofSize: 30)]),
(str: backStr, attr: [NSAttributedString.Key.foregroundColor : UIColor.green, NSAttributedString.Key.font
: UIFont.systemFont(ofSize: 50)])
])
lab.attributedText = attrStr
3.效果图
(情况二: aaBBaa 中间插入的样式),Global.SMEmptyIndicator = "--", Global.SMReplaceIndicator = "****"
Extension String {
/// replace **** use case: 报名10天结束
/// - Parameter newStr: newStr
func replaceXXXX(newStr: String?) -> String {
guard newStr != nil else {
return self.replacingOccurrences(of: Global.SMReplaceIndicator, with: Global.SMEmptyIndicator)
}
return self.replacingOccurrences(of: Global.SMReplaceIndicator, with: newStr!)
}
}
extension UILabel {
/// set UILabel attributes
/// - Parameters:
/// - str: text
/// - color: textColor
/// - fontSize: font.size
func setOriginalAttr(str: String, color: UIColor, fontSize: CGFloat) {
setOriginalAttr(str: str, color: color, font: UIFont.systemFont(ofSize: fontSize))
}
func setOriginalAttr(str: String, color: UIColor, font: UIFont) {
self.text = str
self.textColor = color
self.font = font
}
/// set one part replace "***" of UILabel's text. You must transfer this func after you transferred setOriginalAttr
/// - Parameters:
/// - partStr: this part's text
/// - partColor: this part's text color
/// - partFontSize: this part's font.size
func setPartAttr(partStr: String?, partColor: UIColor, partFontSize: CGFloat) {
setPartAttr(partStr: partStr, partColor: partColor, partFont: UIFont.systemFont(ofSize: partFontSize))
}
func setPartAttr(partStr: String?, partColor: UIColor, partFont: UIFont) {
guard self.text != nil && self.text!.notEmpty else {
return
}
var rightPartStr: String = partStr ?? Global.SMEmptyIndicator
if partStr == nil || partStr!.isEmpty {
rightPartStr = Global.SMEmptyIndicator
}
let tempStr = self.text!.replaceXXXX(newStr: rightPartStr)
let attrS = NSMutableAttributedString(string: tempStr)
guard let tempRange = tempStr.range(of: rightPartStr) else {
return
}
attrS.addAttributes([NSAttributedString.Key.foregroundColor : self.textColor ?? UIColor.black, NSAttributedString.Key.font : self.font ?? UIFont.systemFont(ofSize: 16)], range: NSRange(location: 0, length: tempStr.count))
attrS.addAttributes([NSAttributedString.Key.foregroundColor : partColor, NSAttributedString.Key.font : partFont], range: tempStr.nsRange(from: tempRange))
self.attributedText = attrS
}
}