美文网首页
UILabel显示HTML富文本,响应点击事件

UILabel显示HTML富文本,响应点击事件

作者: ce2f22ad95cd | 来源:发表于2020-07-28 16:18 被阅读0次

    importFoundation

    protocol HtmlLabelDelegate {

        funcclickUrl(url:NSURL)

        funcclickImage(image:UIImage)

    }

    class HtmlLabel: UILabel {

        //Mark --`TextKit` 的核心对象 绘制`textStorage`的文本内容

        /// 属性文本存储

        private lazy var textStorage = NSTextStorage()

        /// 负责文本`字形`布局 1.绘制背景  2.绘制Glyphs 字形 3.获取点中字符的索引

        private lazy var layoutManager = NSLayoutManager()

        /// 设定文本绘制的范围

        private lazy var textContainer = NSTextContainer()

        var delegate:HtmlLabelDelegate?

        var attachments:Array<AttachmentModel> = []

        // Mark: 一旦内容变化 需要让 textStorge 响应变化

        // Mark: --重写属性

        override var text: String?{

            didSet{

                // 重新准备文本内容

                prepareTextSystem()

            }

        }

        override var attributedText: NSAttributedString?{

            didSet{

                // 重新准备文本内容

                prepareTextSystem()

            }

        }

        // Mark: -- 构造函数

        overrideinit(frame:CGRect) {

            super.init(frame: frame)

          prepareTextSystem()

        }

        requiredinit?(coder aDecoder:NSCoder) {

          super.init(coder: aDecoder)

          prepareTextSystem()

        }

        // Mark: --交互

        overridefunctouchesBegan(_touches:Set, with event:UIEvent?) {

            guard let location = touches.first?.location(in:self)else{

               return

            }

            for r in attachments{

                if(r.rect?.contains(location))! {

                    ifr.image!=nil{

                        print("click image")

                        break

                    }else if r.url!=nil{

                        print("click url")

                        break

                    }

                }else{

                    print("没戳着")

                }

            }

        }

        override func drawText(in rect:CGRect) {

            letrange =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

        }

    }

    private extension HtmlLabel{

        ///准备文本系统

        func prepareTextSystem(){

            // 0.开启交互

            isUserInteractionEnabled = true

            //1.准备文本内容

            prepareTextContent()

            //2.设置对象的关系

            textStorage.addLayoutManager(layoutManager)

            layoutManager.addTextContainer(textContainer)

        }

        /// 使用`textStorage`接管label内容

        func prepareTextContent(){

            ifletattributedText =attributedText{

                textStorage.setAttributedString(attributedText)

            }elseiflettext =text{

                textStorage.setAttributedString(NSAttributedString(string: text))

            }else{

                textStorage.setAttributedString(NSAttributedString(string: ""))

            }

            getAttachments()

        }

        func getAttachments(){

            if attributedText == nil {

                return

            }

            attributedText!.enumerateAttributes(in: NSRange(location: 0, length: attributedText!.length), options: NSAttributedString.EnumerationOptions.longestEffectiveRangeNotRequired, using: { (dic, range, stop) in

                        if dic.keys.contains(NSAttributedString.Key.attachment) {

                            let attacment:NSTextAttachment = dic[NSAttributedString.Key.attachment] as! NSTextAttachment

                            ifattacment.fileWrapper!=nil&&attacment.fileWrapper!.regularFileContents!=nil{

                                letrect =boundingRectForCharacterRange(range: range)

                                letattachmentModel =AttachmentModel()

                                attachmentModel.image=UIImage(data: attacment.fileWrapper!.regularFileContents!)

                                attachmentModel.rect= rect

                                attachments.append(attachmentModel)

                            }

                        }else if dic.keys.contains(NSAttributedString.Key.link) {

                            leturl:NSURL= dic[NSAttributedString.Key.link]as!NSURL

                            letrect =boundingRectForCharacterRange(range: range)

                            letattachmentModel =AttachmentModel()

                            attachmentModel.url= url

                            attachmentModel.rect= rect

                            attachments.append(attachmentModel)

                        }

                    })

        }

        private func boundingRectForCharacterRange(range:NSRange) ->CGRect{

            textContainer.lineFragmentPadding = 0

            letglyphRange =layoutManager.characterRange(forGlyphRange: range, actualGlyphRange:nil)

            letrect =layoutManager.boundingRect(forGlyphRange: glyphRange, in:textContainer)

            returnrect

        }

    }

    class AttachmentModel {

        varimage:UIImage?

        varurl:NSURL?

        varrect:CGRect?

    }

    相关文章

      网友评论

          本文标题:UILabel显示HTML富文本,响应点击事件

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