美文网首页iOS Developer
关于图文混排的实现

关于图文混排的实现

作者: 村长大人tardis_cxx | 来源:发表于2017-05-19 18:06 被阅读106次

iOS 图文混排


图文混排,早已成为很多APP必不可少的功能,即一段文字里加入图片,特别是聊天和评论的界面,文字加入表情图片。
那么,如何实现这一功能呢?如今要实现这一功能的框架颇多,但了解实现原理还是有一定的必要性,最近整理笔记,就记录如下,也希望对这方面不太了解的童鞋有所帮助。

思路

  • 实现图文混排,首先要明确用什么控件展示文字和图片,能够展示多行文字的有两个控件,UILabelUITextView
  • 表情键盘是系统表情键盘还是自定义表情键盘,系统表情是emoji表情,是十六进制字符串,不需要做特别处理,就能够展示
  • 如果是自定义表情键盘,那么一般大都是小图标,那么就应该有图片名,有的应该还有对应的表情名,如:[呵呵]
  • 对于自定义表情的话,那么一般情况下,我使用属性字符串来修改局部文字颜色,用正则表达式获取表情名,再转为属性字符串,设置大小,最后展示在控件上
  • 当然属性字符串,有的叫富文本

实现

一般情况下,对于这种功能,有太多地方需要用到,我会进行封装,可以给NSString写分类,也可以专门创建属性字符串管理者来实现:

class TCAttibuteStingManager {
    
}

extension TCAttibuteStingManager {
    
    class func greateNormalAttibutesString(_ username: String, _ message: String) -> NSAttributedString {
        let str = username + message
        
        // 创建NSMutableAttributedString
        let attrStr = NSMutableAttributedString(string: str)
        
        // 修改名字颜色
        let nameRange = NSRange(location: 0, length: username.characters.count)
        attrStr.setAttributes([NSForegroundColorAttributeName: UIColor.orange], range: nameRange)
        
        return attrStr
    }
}

以上只是对普通字符串转为属性字符串的函数,就可以实现名字高亮,其他文字普通状态的样式,图文混排只是更进一步而已,如下:

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 [抱抱]!
        // []为图片字符串,需要替换为图片
        // 图文混排,使用正则表达式
        // .*?
        // 匹配规则
        let pattern = "\\[.*?\\]"
        guard let reg = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) else {
            return attrStr
        }
        
        // 匹配结果
        let range = NSRange(location: 0, length: str.characters.count)
        let results = reg.matches(in: str, options: [], range: range)
        
        // 遍历匹配结果
        // 倒序遍历
        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
            }
            
            // 创建NSTextAttachment
            let attachment = NSTextAttachment()
            attachment.image = image
            attachment.bounds = CGRect(x: 0, y: -4, width: font.lineHeight, height: font.lineHeight)
            
            // 创建图片NSAttributedString
            let imageAttrStr = NSAttributedString(attachment: attachment)
            
            // 替换
            attrStr.replaceCharacters(in: result.range, with: imageAttrStr)
        }
        
        return attrStr
}

由上面可知,核心代买是for循环内部,创建NSTextAttachment,然后根据匹配结果,把NSTextAttachment对象转为属性字符串!如此,一个简单的图文混排就搞定了。

还有一种图文混排,就是需要下载图片,比如聊天记录,给主播送礼物消息等等,代码如下:

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个函数,直接拷贝就可使用,至于其他如链接高亮等等,还需要其他匹配规则,童鞋们可再做扩展。

相关文章

网友评论

    本文标题:关于图文混排的实现

    本文链接:https://www.haomeiwen.com/subject/cooyxxtx.html