美文网首页
Swift_富文本绘制以及Url的点击

Swift_富文本绘制以及Url的点击

作者: 走停2015_iOS开发 | 来源:发表于2018-05-07 11:27 被阅读520次
    541AAB10-735B-49DA-8CC9-99E8020662E8.png
    TextKit 的核心对象
    • 属性文本存储
      private lazy var textStorage = NSTextStorage()
    • 负责文本字形布局
      1. 绘制背景
      2. 绘制Glyphs 字形
      3. 获取点中字符的索引
      private lazy var layoutManager = NSLayoutManager()
    • 设定文本绘制的范围
      private lazy var textContainer = NSTextContainer()
    1 .label的扩展
    • 准备文本系统
    • 使用textStorage接管label内容
    private extension AttLabel
    {
        ///准备文本系统
        func prepareTextSystem()
        {
            // 0.开启交互
            isUserInteractionEnabled = true
            //1.准备文本内容
            prepareTextContent()
            //2.设置对象的关系
          textStorage.addLayoutManager(layoutManager)
          layoutManager.addTextContainer(textContainer)
            
        }
        /// 使用`textStorage`接管label内容
        func prepareTextContent()
        {
            if let attributedText = attributedText
            {
    textStorage.setAttributedString(attributedText)
            }else if let text = text
            {
    textStorage.setAttributedString(NSAttributedString(string: text))
            }else
            {
    textStorage.setAttributedString(NSAttributedString(string: ""))
            }
         //遍历范围数组 设置URL 文字的属性
            for r in urlRanges ?? [] {
        textStorage.addAttributes([NSAttributedStringKey.foregroundColor:UIColor.red,
    NSAttributedStringKey.backgroundColor:UIColor.blue], range: r)
            }
        }
    }
    
    2. 使用正则表达式
    • 返回 textStorge 中的Url的范围数组
    private extension AttLabel
    {
         var urlRanges:[NSRange]?
        {
         // 1.正则表达式
            let pattern = "[a-zA-Z]*://[a-zA-z0-9/\\.]*"
            guard let regx = try? NSRegularExpression(pattern: pattern,
     options: []) else{
                return nil
            }
          // 2.多重匹配
        let matches =  regx.matches(in: textStorage.string, 
    options: [], range: NSRange(location: 0, length: textStorage.length))
          // 3.遍历数组 生成range数组
            var ranges = [NSRange]()
            for m in matches {
            ranges.append(m.range(at: 0))
            }
          return ranges
        }
    }
    
    3. 自定义label
    • 重写text属性
    • 准备文本系统
    • 交互 touchesBegan
    class AttLabel: UILabel {
       //Mark --`TextKit` 的核心对象 绘制`textStorage`的文本内容
        /// 属性文本存储
        private lazy var textStorage = NSTextStorage()
        /// 负责文本`字形`布局 1.绘制背景  2.绘制Glyphs 字形 3.获取点中字符的索引
        private lazy var layoutManager = NSLayoutManager()
        /// 设定文本绘制的范围
        private lazy var textContainer = NSTextContainer()
        
        // Mark: 一旦内容变化 需要让 textStorge 响应变化
        // Mark: --重写属性
        override var text: String?
            {
            didSet{
                // 重新准备文本内容
                prepareTextSystem()
            }
        }
        // Mark: -- 构造函数
        override init(frame: CGRect) {
            super.init(frame: frame)
          prepareTextSystem()
        }
        required init?(coder aDecoder: NSCoder) {
          super.init(coder: aDecoder)
          prepareTextSystem()
        }
        // Mark: --交互
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            /// 获取用户点击位置
            guard let location = touches.first?.location(in: self) else{
               return
            }
            /// 获取点中字符的索引
            let index =
            layoutManager.glyphIndex(for: location, in: textContainer)
            /// 判断index是否在ranges的范围内 如果在 就高亮
            for r in urlRanges ?? [] {
             if NSLocationInRange(index,r)
             {
        textStorage.addAttributes([NSAttributedStringKey.foregroundColor:UIColor.white], range: r)
            /// 如果需要重绘 需要调用一个函数 但不是drawRect
             setNeedsDisplay()
             }else
             {
             print("没戳着")
            }
            }
            
            
        }
        override func drawText(in rect: CGRect) {
        
            let range = NSRange(location: 0, length: textStorage.length)
            /// 绘制背景
            layoutManager.drawBackground(forGlyphRange: range, at: CGPoint())
            /// 绘制Glyphs 字形
            /// CGPoint():从原点绘制
            layoutManager.drawGlyphs(forGlyphRange: range, at: CGPoint())
        }
        
        override func layoutSubviews() {
            super.layoutSubviews()
            //指定绘制文本的区域
            textContainer.size = bounds.size
            
        }
    }
    

    相关文章

      网友评论

          本文标题:Swift_富文本绘制以及Url的点击

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