SWIFT实现图文混排

在网上搜索图文混排的帖子,有好多。。大多用的第三框架,但是swift实现图文混排的帖子还真不多,我在这里和大家一起梳理一下。希望彼此都能有所帮助,

废话不多说,进入正题:

首先我们都知道,图文混排主要是用在UITextView/ UILab / UITextFiled 等能够输入或者显现表情与文字的控件中,主要用到的属性是NSAttributeText,因此,我们基本上可以把图文混排分为三部分内容

1. 表情键盘的创建(将表情包中的表情添加到键盘上)

2. 点击表情时,表情能够与文字同时显示到输入框上

3. 可以上传到服务器,并且在前端显示出来

现在我们就开始分别总结一下这三点:

1. 表情键盘的创建

首先是表情源的获取,基本上是一个NSBundle文件,里面装几个表情文件夹,我们获取到每一个图片,然后赋值到表情键盘的button上,表情键盘的实质也就是一个UICollectionView,每个cell上放了若干了button,这一部分比较简单。我们就不做过多的赘述,有兴趣的同学可以直接看代码<EmoticonView.swift>

2. 表情键盘显示到输入框

//通过点击表情按钮,发送通知,将button传递过来,里面包含了自身的表情模型

 let imageName = "\(path)/\(png)"
       
 // 创建NSMutableAttributedString对象
        let attributeMutableString = NSMutableAttributedString(attributedString: textV.attributedText)

        let textAttachment = NSTextAttachment()

        //设置textAttachment的大小和属性
        textAttachment.bounds = CGRectMake(0, -5, (textV.font!.lineHeight), textV.font!.lineHeight)
       
       
 //获取当前的光标位置
        textAttachment.image = UIImage(named: imageName)
   
       
 let attributeString = NSAttributedString(attachment: textAttachment)
       
       
 //设置位置,替换
        let range =  textV.selectedRange
       
        attributeMutableString.
replaceCharactersInRange(range, withAttributedString: attributeString)
       

        attributeMutableString.
addAttributes([NSFontAttributeName: textV.font!], range: NSMakeRange(0, attributeMutableString.length))
       
       
       
 //MARK:设置表情的大小
        textV.attributedText = attributeMutableString
       
       
 //让光标回到下一个位置
       
 textV.selectedRange = NSMakeRange(range.location + 1, 0)
       
        }
       
       
 if let emoji = emoticon?.emoji {
       
           
 textV.replaceRange(textV.selectedTextRange!, withText: emoji)
           
        }


3. 表情文本的上传到服务器,首先我们要清楚一下,发布到服务器都必须是字符串形式,这就需要我们在上传之前,将textView的attributeText全部转化为字符串,

func transformToString () ->String {
       
var publishString: String= String()
       
       
self.attributedText.enumerateAttributesInRange(NSMakeRange(0,self.attributedText.length), options: []) { (data, range, _) -> Void in
           
                iflet dataDict = data as? [String: AnyObject] {
               
            if let attachment = dataDict["NSAttachment"] {
                   
                   
             //attachment强制转为YDTextAttachment
               let YDattachment = attachment as! YDTextAttachment
         
                    //将表情转为文字,需要在NSAttachment里面有emoticon模型
                publishString = publishString + (YDattachment.emoticon?.chs)!
                   
                   
                }
else{
  
                   
//self.textV.text按照范围进行切割
                    print(range)
                   
                   
let subString = (self.textas NSString).substringWithRange(range)
   
                    publishString = publishString + subString
                   
                   
                }
               
            }
    }
   
       
return publishString

    }

最后就是从服务器获取到的有表情的text在前端的展示,这块用到了正则表达式, 里面用到了两个方法

class func getAttributeString(emoticon:HMEmoticon? ,font: UIFont) -> NSAttributedString? {

    // 1. 创建一个附件对象

        let attachment = HMTextAttachment()

        // 1.1 拼接图片路径

        guard let path = emoticon?.path,png = emoticon?.png else {

            return nil

        }

        let imagePath = "\(path)/\(png)"

        // 1.2 设置他的属性

        attachment.image = UIImage(named: imagePath)

        // 1.3 修改图片的bounds

        // 思考表情的宽高怎么设置?

        let lineHeght = font.lineHeight

        attachment.bounds = CGRectMake(0,-5, lineHeght, lineHeght)

     // 2. 创建一个NSAttributeString对象

        let attribute = NSAttributedString(attachment: attachment)

        

        return attribute

    }

 private func dealEmoticonText(text: String?) -> NSAttributedString {

        

        guard let text = text else  {

            return NSAttributedString()

        }

        

        // 定义一个 全局AttributeString

        let globleAttribute = NSMutableAttributedString(string: text)

        

        // 1. 把表情的对象HMEmotion,发送给了 HMPublishViewController

        // 2. 创建了一个NSAttributeString, 拥有一个附件.NStextAttachment, image

        // 3. textViewAttribute = attribute

        

        /*

            text -- 微博内容含有表情的情况有多种

            1.没有表情

            2.有一个表情 -> [微笑]

            3.有多个表情

        */

        // I [嘻嘻] U

        

        /*

        

        . 匹配任意字符,除了换行

        

        () 锁定要查找的内容

        

        * 匹配任意长度的内容

        

        ?尽量少的匹配

        

            \\[.*?\\]

        */

        // 分析正则为主

         let pattern = "\\[.*?\\]"

        

        /*

            默认的try

            try?

            try!

        */

        do {

            /*

                第一个参数正则表达式

                第二个参数针对正则表达式的一些设置不要刻意去记,学一个记一个

            */

            

            // 1. 创建正则

            let regx = try NSRegularExpression(pattern: pattern, options: .DotMatchesLineSeparators)

            

            // 2. 让正则去匹配查找

            /*

                第一个参数指定查找的字符串

                第二个参数默认值

                第三个参数范围

            */

            let results =  regx.matchesInString(text, options: [], range: NSMakeRange(0, text.characters.count))

            

            // 3. 就是对 查找结果进行遍历

            //  NSTextCheckingResult

            

            for (_,result) in results.reverse().enumerate() {

                

                // 获取查找结果的range

                let range = result.range

                // 通过range来获取查找的表情字符串 

                let emoticonString = (text as NSString).substringWithRange(range)

                // 通过表情字符串,转换成表情对象

                let emoticon = HMEmoticonManager.searchEmoticon(emoticonString)

                

                let attachment = HMTextAttachment()

                

                attachment.emoticon = emoticon

                

                let attribute = attachment.getAttributeString(UIFont.systemFontOfSize(16))

             

                // 通过类方法,可以变成一行代码

                let attribute2 = HMTextAttachment.getAttributeString(emoticon, font: UIFont.systemFontOfSize(16))

                

                

                // globleAttribute = I  U

                // 进行一个替换

                globleAttribute.replaceCharactersInRange(range, withAttributedString: attribute!)

                

            }

            

            /* 第一次打印还没有进行替换: I [嘻嘻] [嘻嘻] U{

        }

        ~~~~~~~~~~~~~~~~~

            

            第二次打印

            I {

            }{

            NSAttachment = "<NSTextAttachment: 0x7fbd787f9c00>";

            } [嘻嘻] U{

            }

            

*/

            // 遍历结束之后,再返回

            return globleAttribute

            

        } catch {

            printLog(error)

        }

        

        return NSAttributedString()

    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值