美文网首页
iOS 搜索文本在 UILabel 上的显示

iOS 搜索文本在 UILabel 上的显示

作者: Yuency | 来源:发表于2018-05-14 11:17 被阅读78次

前言

项目做了个搜索功能, 这个搜索功能有个很烦的显示样式, 这个样式竟然花了我两天的时间去搞定. 我才不是一个菜鸟程序猿

代码地址: https://github.com/gityuency/Autolayout

需求概述
  1. 在文本框里面输入文本, 将输入的字符和目标字符进行匹配, 把匹配到的结果显示在 Label 上, (其实就是使用一下网易云信的文本搜索功能,把搜索到的消息显示出来.)
  2. 如果这条消息很短, 那么, 在 Label 上完全显示, 这个没有问题.
  3. 如果这个消息很长, 那么 Label 是显示不全的, 这个时候, 要把匹配到的字符高亮显示出来.
  4. 如果匹配到的字符在目标字符串中间, 那么 Label 前后打上省略号.
  5. 如果匹配到的字符在目标字符串后面, 那么 Label 前面打上省略号.
  6. 如果匹配到的字符在目标字符串前面, 那么 Label 后面打上省略号.
  7. 如果目标字符串有多个子串被匹配到了, 那么取左边开始第一个匹配的到的子串并高亮.

我觉得作为一个程序猿, 上面的需求我写的很清晰.

效果图


搜索.gif

关键代码
(注意, 这并不是全部代码, 这段关键代码引用了一个 字符串扩展用来查找位置, 一个 富文本扩展用来高亮显示, 完整示例请下载项目)

/// 搜索文本的显示工具
class MessageDisplayTool {
    
    /// 匹配字符串,更改 Label 显示样式
    static func handleDisplayMessage(searchTxt: String, oriString: String, messageLabel: UILabel) {
        
        messageLabel.superview?.layoutIfNeeded()
        
        /// 除掉多余的换行
        let fatherString = oriString.replacingOccurrences(of: "\r", with: "").replacingOccurrences(of: "\n", with: "")
        
        /// 找到匹配文本从左到右第一次出现的位置
        let position1 = fatherString.lowercased().positionOf(sub: searchTxt.lowercased())
        
        if position1 < 0 {
            messageLabel.text = searchTxt
            return
        }
        
        let labelWidth = messageLabel.frame.size.width
        let labelFont = messageLabel.font ?? UIFont.systemFont(ofSize: 17.0)

        var indexFirst = position1 < 0 ? 0 : (position1 + searchTxt.count)
        indexFirst = (indexFirst + 3) < fatherString.count ? (indexFirst + 3) : indexFirst //如果搜索的文本出现在了目标文本中间, 为了显示好看, 多往后显示3个文字
        let i1 = fatherString.index(fatherString.startIndex, offsetBy: indexFirst)
        let actuallyCleanURL = fatherString[..<i1]
        let finalString = String(actuallyCleanURL)
        let size: CGSize = finalString.size(withAttributes: [NSAttributedStringKey.font: labelFont])  //取第一次匹配到的结果,往后多截3个文字,然后拿宽度去比较
        
        let of2 =  position1 < 0 ? 0 : position1
        let start = fatherString.index(fatherString.startIndex, offsetBy: of2)
        let i2String = fatherString[start..<fatherString.endIndex]  //这里取的是 第一次搜索到的子串 到 父串尾部的 串, 然后拿到宽度
        let finalString2 = String(i2String)
        let size2_W = finalString2.size(withAttributes: [NSAttributedStringKey.font: labelFont]).width
        
        if labelWidth > size.width {  //这里要把最终字符串的宽度和 Label 的宽度进行比较, 才能确定显示的样式
            messageLabel.attributedText = MessageDisplayTool.attriMessage(searchTxt: searchTxt, oriString: fatherString)
            messageLabel.lineBreakMode = .byTruncatingTail
        } else {
            if size2_W < labelWidth {  //如果子串的宽度小于 Label 宽度,就显示父串
                messageLabel.attributedText = MessageDisplayTool.attriMessage(searchTxt: searchTxt, oriString: fatherString)
            } else {                   //如果子串的宽度大于 Label 宽度,就显示子串, 这个子串是截取后的
                messageLabel.attributedText = MessageDisplayTool.attriMessage(searchTxt: searchTxt, oriString: "\(finalString)...")
            }
            messageLabel.lineBreakMode = .byTruncatingHead
        }
    }
    
    /// 添加富文本高亮
    static func attriMessage(searchTxt: String, oriString: String) -> NSAttributedString {
        let attri: NSAttributedString = NSAttributedString(string: oriString)
        let newAttri = attri.applying(attributes: [NSAttributedStringKey.foregroundColor: UIColor.red], toOccurrencesOf: searchTxt)
        return newAttri;
    }
    
}

相关文章

网友评论

      本文标题:iOS 搜索文本在 UILabel 上的显示

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