直接上代碼肠仪,通過(guò)以下計(jì)算就可以完成鏈接的識(shí)別以及替換肖抱,然后添加高亮以及對(duì)高亮文字添加點(diǎn)擊事件
let label = YYLabel()
label.backgroundColor = .red
label.numberOfLines = 0
label.preferredMaxLayoutWidth = 200
view.addSubview(label)
label.snp.makeConstraints { (make) in
make.left.equalTo(50)
make.width.equalTo(200)
make.top.equalTo(300)
}
var urls: [String] = []
var string = "test\\n\ntest/\\n\n??\nhttps://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_9827769369551786176%22%7D&n_type=0&p_from=1 第二個(gè) https://weibo.com/mygroups?gid=201209041125312675&wvr=6&leftnav=1&isspecialgroup=1 今天又是好天氣!今天又是好天氣异旧!今天又是好天氣意述!今天又是好天氣!今天又是好天氣吮蛹!";
// var string = "est\\n\ntest/\\n\n??\nhttps://www.weibo.com/beat/beatslist/beat?keyword=測(cè)試 https://weibo.com/mygroups?gid=201209041125312675&wvr=6&leftnav=1&isspecialgroup=1 每天都很美好";
let detector = try? NSDataDetector.init(types: NSTextCheckingResult.CheckingType.link.rawValue)
let matches = detector?.matches(in: string, options: [.reportProgress], range: NSRange(location: 0, length: string.count))
for match in matches! {
if match.resultType == .link {
if let url = match.url {
//這里獲取到的url是經(jīng)過(guò)encode處理的
urls.append(url.absoluteString)
}
}
}
print("encode urls \(urls)")
let font = UIFont.systemFont(ofSize: 15)
let attribbutes = NSMutableAttributedString(string: "")
for str in urls {
var strArray = string.components(separatedBy: str)
if strArray.count < 2 {
//如果沒(méi)有匹配到字符說(shuō)明string沒(méi)有經(jīng)過(guò)encode欲险,但是str為encode以后的字符,所以需要decode str才能識(shí)別
if let decode = str.removingPercentEncoding {
strArray = string.components(separatedBy: decode)
}
}
if let firstStr = strArray.first {
let subAttribute = NSMutableAttributedString(string: firstStr)
subAttribute.setColor(.cyan, range: NSRange(location: 0, length: firstStr.count))
attribbutes.append(subAttribute)
let hightText = YYTextHighlight()
hightText.tapAction = { view, text, range, rect in
guard let url = URL(string: str) else {
print("error url \(str)")
return
}
print("open url \(url)")
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
let imageAttribute = NSMutableAttributedString.attachmentString(withContent: UIImage(named: "commend_kink"), contentMode: .scaleAspectFit, attachmentSize: .init(width: 18, height: 18), alignTo: font, alignment: .center)
let replaceStr = NSMutableAttributedString(string: "查看鏈接")
replaceStr.setColor(.yellow, range: NSRange(location: 0, length: 4))
imageAttribute.append(replaceStr)
imageAttribute.setTextHighlight(hightText, range: NSRange(location: 0, length: 5))
attribbutes.append(imageAttribute)
}
if let lastStr = strArray.last {
string = lastStr
}
}
let lastAttribute = NSMutableAttributedString(string: string)
lastAttribute.setColor(.cyan, range: NSRange(location: 0, length: string.count))
attribbutes.append(lastAttribute)
label.attributedText = attribbutes
注意點(diǎn)YYLabel UILabel用法差異
使用YYLabel和使用UILabel還是有一些區(qū)別的匹涮。如果使用UILabel設(shè)置了lable的font、textColor槐壳,在給label的text賦值或者attributedText賦值時(shí)然低,上述設(shè)置都會(huì)生效。但是YYLabel設(shè)置font务唐、textColor只會(huì)對(duì)label的text生效雳攘,對(duì)于attributedText屬性必須對(duì)NSAttributedString、NSMutableAttributedString進(jìn)行設(shè)置枫笛。
YYLabel高度自適應(yīng) preferredMaxLayoutWidth
對(duì)于UIlabel僅設(shè)置label.numberOfLines = 0吨灭,并且不設(shè)置高度lable就會(huì)隨著顯示內(nèi)容自動(dòng)增長(zhǎng),但是對(duì)于YYLable除了設(shè)置label.numberOfLines = 0刑巧,還要設(shè)置label.preferredMaxLayoutWidth喧兄,只有這樣YYLabel才會(huì)自增長(zhǎng)。
String NSString 對(duì)于表情NSRange計(jì)算長(zhǎng)度不同
由下圖可以看出對(duì)于純文字不管是String類(lèi)型NSString計(jì)算結(jié)果都一樣啊楚。但是對(duì)于含有表情的文本計(jì)算吠冤,兩者計(jì)算結(jié)果不一樣。對(duì)于這種情況可以使用NSString計(jì)算也可以使用String調(diào)用.utf16.coun計(jì)算恭理。NSString默認(rèn)使用utf16計(jì)算拯辙,而表情大部分也需要使用utf16計(jì)算,所以直接使用NSString就可以得到正確的結(jié)果颜价。
let range = NSMakeRange(0, string.count)
let nsStr = string as NSString
let conTentRange = NSMakeRange(0, nsStr.length)
//let conTentRange = NSMakeRange(0, string.utf16.count)
printf("range \(range) conTentRange \(conTentRange) text \(text)")
YYTextHighlight和父視圖手勢(shì)會(huì)沖突問(wèn)題
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
//YYTextHighlight和父視圖手勢(shì)會(huì)沖突涯保,所以需要識(shí)別點(diǎn)擊位置是否包含YYTextHighlight
if touch.view is YYLabel {
let label = touch.view as? YYLabel
if let label = label {
var range = NSMakeRange(0, 1);
let highlight = label._getHighlight(at: touch.location(in: label), range: &range)
if highlight != nil {
return false
}
}
}
return true
}
上邊代碼中-(YYTextHighlight *)_getHighlightAtPoint:(CGPoint)point range:(NSRangePointer)range;為私有方法,外部不可調(diào)用周伦,又考慮到引用的是別人的第三方庫(kù)夕春,所以需要?jiǎng)?chuàng)建一個(gè)YYLabel的分來(lái),然后將此方法在YYLabel分類(lèi)的.h中聲明专挪。如下:
#import "YYLabel.h"
NS_ASSUME_NONNULL_BEGIN
@interface YYLabel (YHYYLabel)
- (YYTextHighlight *)_getHighlightAtPoint:(CGPoint)point range:(NSRangePointer)range;
@end
NS_ASSUME_NONNULL_END