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 . text as 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()

    }



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值