swift 聊天表情emoji转译——从键盘到输入框

Posted ihoudf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swift 聊天表情emoji转译——从键盘到输入框相关的知识,希望对你有一定的参考价值。

题记

做聊天框时,遇到了几个麻烦事,在此记录,以备自查,其他观者仅供参考。有更好的做法,也请赐教。​​​​​​​

代码并不可直接复制使用。写博客时,添加了详细的注释,标明每段代码的用途。

正文

聊天输入框文字和表情输入,输入完后显示在聊天列表。

有几个麻烦的地方:

1、输入时表情转译。由图片转成[dog]。转译并不麻烦,关键是表情所在的位置。

2、显示到列表时的再转成表情。

3、图文混排

4、等等等等,很多小细节

逻辑1:点击表情键盘的一个表情后,如何显示到输入框里。

// 关键点:自定义一个attachment,用来存储表情的转译后的文字
class TalkfunAttachment: NSTextAttachment 
    var displayText: String?

// 点击表情键盘一个表情,获得表情名称,并显示到输入框
func appendImage(_ emoji: String) 
        guard let image = UIImage(named: emoji) else  return 
                
        // 限制最大输入字符
        if inputV.attributedText.length > 50 
            return
        
        // 输入框内容不为空,发送按钮变颜色
        self.sendBtn.backgroundColor = .hexColor("#1F9752")
        // 记录光标位置,有可能从文字中插入表情
        let currentLocation = inputV.selectedRange.location
        
        // 构造图片富文本
        let newH = 20.0
        let newW = newH * image.size.width / image.size.height
        let font = UIFont.systemFont(ofSize: 15)
        let newY = roundf(Float(font.capHeight - newH))/2.0

        let attach = TalkfunAttachment()
        attach.displayText = "[\\(emoji)]" // 注意这里
        attach.image = image
        attach.bounds = CGRect(x: 0, y: Double(newY), width: newW, height: newH)
        let imgStr = NSMutableAttributedString(attachment: attach)
        // 获取输入框已有的内容
        let oldStr = NSMutableAttributedString(attributedString: self.inputV.attributedText)
        // 插入表情字符串
        oldStr.insert(imgStr, at: currentLocation)
        // 对整个内容设置UI属性
        oldStr.addAttributes(self.getAttr(), range: NSMakeRange(0, oldStr.length))
        // 赋值给输入框
        self.inputV.attributedText = oldStr
        
        // 让输入框高度随内容变化
        fitSizeForTextView()

        // 重新设置光标
        inputV.selectedRange = NSMakeRange(currentLocation + imgStr.length, 0)
    
  // 让输入框的高度随着内容而变化。最高110,最低50
    func fitSizeForTextView() 
        let newHeight = inputV.sizeThatFits(CGSize(width: inputV.frame.size.width, height: inputV.frame.size.height)).height
        var viewH = newHeight + 10 + 4
        viewH = viewH < 50 ? 50 : viewH
        if viewH > 110 
            viewH = 110
        
        self.snp.updateConstraints  (make) in
            make.height.equalTo(viewH)
        
    

    /// 输入框内容的富文本UI属性
    private func getAttr() -> [NSAttributedString.Key : Any] 
        let style = NSMutableParagraphStyle()
        style.lineSpacing = 2
        let attr = [NSAttributedString.Key.paragraphStyle : style,
                    NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16),
                    NSAttributedString.Key.foregroundColor : UIColor.hexColor("#303030")
        ]
        return attr
    

逻辑2:输入框有文字有图片,UITextView的text属性没有表情的信息,如何在添加了表情的输入框里继续追加文本呢。

   // MARK: - delegate
    // 为应对复制内容到文本框等情况,需要在此代理实时更新内容的富文本属性
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool 
        inputV.typingAttributes = getAttr()
        return true
    
    
    func textViewDidChange(_ textView: UITextView) 

        // 输入内容不是可选状态时去设置
        if inputV.markedTextRange == nil || inputV.markedTextRange?.isEmpty ?? false 
            // 根据有无内容,设置发送按钮颜色
            sendBtn.backgroundColor = inputV.attributedText.length > 0 ? .hexColor("#1F9752") : .hexColor("#CCCCCC")
            
            let range = inputV.selectedRange

            // 设置内容属性,并设置最大字符数
            let attrText = NSMutableAttributedString(attributedString: inputV.attributedText)
            attrText.addAttributes(getAttr(), range: NSRange(location: 0, length: attrText.length))
            
            // 最大字符
            if attrText.length > 50  // 限制最大长度
                attrText.deleteCharacters(in: NSMakeRange(50, attrText.length - 50))
            
            
            inputV.attributedText = attrText
            inputV.selectedRange = range
            
            // 根据内容设置输入框高度
            fitSizeForTextView()
        
    
    

逻辑3:点击发送按钮,发送的是转译后的文字内容。如何解析输入框的文字和表情 得到最后的转译内容?例如:

输入框的内容显示的是:哈哈😄🌹,你好啊🌹

怎么得到:哈哈[haha][meigui],你好啊[meigui]

    func getInputText() -> String? 

        // 获取输入框所有的内容
        let returnStr = NSMutableAttributedString(attributedString: self.inputV.attributedText)

        guard let attrText = self.inputV.attributedText else 
            return nil
        

        // 最关键的地方:::    
        // 遍历attachment,用attachment的displayText去替换attachment。
        // 把图片富文本换成转译后的文字内容,例如用[haha]替换😄
        attrText.enumerateAttribute(NSAttributedString.Key.attachment, in: NSMakeRange(0, attrText.length), options: .reverse)  value, range, _ in
            if value is TalkfunAttachment 
                
                if let attach = value as? TalkfunAttachment, let emojiStr = attach.displayText 
                    let newRange = NSMakeRange(range.location, range.length)
                    returnStr.replaceCharacters(in: newRange, with: emojiStr)
                
            
        
        
        let text = returnStr.string

        print("解析结束:" + text)
        return text
    

结尾:

至此,我们完成从键盘点击表情 到点击发送 得到转译文字内容。

发送成功之后,如何解析文本,展示到聊天列表呢?请查看:

swift 聊天表情emoji转译(二)(从转译文字到聊天列表)_ihoudf的博客-CSDN博客// 解析消息 获取图文混排字符串 // func getMsgAttrText(msg: String) -> NSMutableAttributedString // 获取所有表情range var tempText = msg var allRanges: [NSRange] = [] for str in customEmojiArray let n...https://blog.csdn.net/HDFQQ188816190/article/details/124630206?spm=1001.2014.3001.5502

以上是关于swift 聊天表情emoji转译——从键盘到输入框的主要内容,如果未能解决你的问题,请参考以下文章

swift 聊天表情emoji转译——从键盘到输入框

swift 聊天表情emoji转译——从转译文字到聊天列表

swift 聊天表情emoji转译——从转译文字到聊天列表

swift 聊天表情emoji转译——从转译文字到聊天列表

React-native:打开表情符号键盘

qq表情emoji怎么打出来?