iOS 圖文混排
圖文混排盾碗,早已成為很多APP必不可少的功能媚污,即一段文字里加入圖片舀瓢,特別是聊天和評(píng)論的界面,文字加入表情圖片耗美。
那么京髓,如何實(shí)現(xiàn)這一功能呢?如今要實(shí)現(xiàn)這一功能的框架頗多商架,但了解實(shí)現(xiàn)原理還是有一定的必要性堰怨,最近整理筆記,就記錄如下蛇摸,也希望對(duì)這方面不太了解的童鞋有所幫助备图。
思路
- 實(shí)現(xiàn)圖文混排,首先要明確用什么控件展示文字和圖片,能夠展示多行文字的有兩個(gè)控件揽涮,
UILabel
和UITextView
- 表情鍵盤是系統(tǒng)表情鍵盤還是自定義表情鍵盤抠藕,系統(tǒng)表情是emoji表情,是十六進(jìn)制字符串蒋困,不需要做特別處理盾似,就能夠展示
- 如果是自定義表情鍵盤,那么一般大都是小圖標(biāo)雪标,那么就應(yīng)該有圖片名零院,有的應(yīng)該還有對(duì)應(yīng)的表情名,如:[呵呵]
- 對(duì)于自定義表情的話村刨,那么一般情況下告抄,我使用屬性字符串來修改局部文字顏色,用正則表達(dá)式獲取表情名烹困,再轉(zhuǎn)為屬性字符串玄妈,設(shè)置大小,最后展示在控件上
- 當(dāng)然屬性字符串髓梅,有的叫富文本
實(shí)現(xiàn)
一般情況下拟蜻,對(duì)于這種功能,有太多地方需要用到枯饿,我會(huì)進(jìn)行封裝酝锅,可以給NSString寫分類,也可以專門創(chuàng)建屬性字符串管理者來實(shí)現(xiàn):
class TCAttibuteStingManager {
}
extension TCAttibuteStingManager {
class func greateNormalAttibutesString(_ username: String, _ message: String) -> NSAttributedString {
let str = username + message
// 創(chuàng)建NSMutableAttributedString
let attrStr = NSMutableAttributedString(string: str)
// 修改名字顏色
let nameRange = NSRange(location: 0, length: username.characters.count)
attrStr.setAttributes([NSForegroundColorAttributeName: UIColor.orange], range: nameRange)
return attrStr
}
}
以上只是對(duì)普通字符串轉(zhuǎn)為屬性字符串的函數(shù)奢方,就可以實(shí)現(xiàn)名字高亮搔扁,其他文字普通狀態(tài)的樣式,圖文混排只是更進(jìn)一步而已蟋字,如下:
class func greateChatMessage(_ username: String, _ message: String, font: UIFont) -> NSAttributedString {
let str = username + ":" + message
let attrStr = NSMutableAttributedString(string: str)
let nameRange = NSRange(location: 0, length: username.characters.count)
attrStr.setAttributes([NSForegroundColorAttributeName: UIColor.orange], range: nameRange)
// 字符串稿蹲,如:i [愛心] you [色] girl [抱抱]!
// []為圖片字符串鹊奖,需要替換為圖片
// 圖文混排苛聘,使用正則表達(dá)式
// .*?
// 匹配規(guī)則
let pattern = "\\[.*?\\]"
guard let reg = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) else {
return attrStr
}
// 匹配結(jié)果
let range = NSRange(location: 0, length: str.characters.count)
let results = reg.matches(in: str, options: [], range: range)
// 遍歷匹配結(jié)果
// 倒序遍歷
for i in (0..<results.count).reversed() {
let result = results[i]
let imageName = (str as NSString).substring(with: result.range)
guard let image = UIImage(named: imageName) else {
continue
}
// 創(chuàng)建NSTextAttachment
let attachment = NSTextAttachment()
attachment.image = image
attachment.bounds = CGRect(x: 0, y: -4, width: font.lineHeight, height: font.lineHeight)
// 創(chuàng)建圖片NSAttributedString
let imageAttrStr = NSAttributedString(attachment: attachment)
// 替換
attrStr.replaceCharacters(in: result.range, with: imageAttrStr)
}
return attrStr
}
由上面可知,核心代買是for循環(huán)內(nèi)部忠聚,創(chuàng)建NSTextAttachment
设哗,然后根據(jù)匹配結(jié)果,把NSTextAttachment
對(duì)象轉(zhuǎn)為屬性字符串两蟀!如此网梢,一個(gè)簡單的圖文混排就搞定了。
還有一種圖文混排赂毯,就是需要下載圖片战虏,比如聊天記錄拣宰,給主播送禮物消息等等,代碼如下:
class func createImageMessage(_ userName: String, _ imageName: String, _ imageUrl: String, font: UIFont) -> NSAttributedString {
let str = userName + ":xxxxxx" + imageName
let attrStr = NSMutableAttributedString(string: str)
let nameRange = NSRange(location: 0, length: userName.characters.count)
attrStr.setAttributes([NSForegroundColorAttributeName: UIColor.orange], range: nameRange)
let imageNameRange = (imageName as NSString).range(of: imageName)
attrStr.setAttributes([NSForegroundColorAttributeName: UIColor.orange], range: imageNameRange)
// 下載圖片
guard let image = KingfisherManager.shared.cache.retrieveImageInMemoryCache(forKey: imageUrl) else {
return attrStr
}
let attachment = NSTextAttachment()
attachment.image = image
attachment.bounds = CGRect(x: 0, y: -4, width: font.lineHeight, height: font.lineHeight)
let imageAttr = NSAttributedString(attachment: attachment)
// 拼接
attrStr.append(imageAttr)
return attrStr
}
以上3個(gè)函數(shù)烦感,直接拷貝就可使用徐裸,至于其他如鏈接高亮等等,還需要其他匹配規(guī)則啸盏,童鞋們可再做擴(kuò)展重贺。