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?
}
参考富文本:LayaAir下 HtmlDivElement的使用汇总 富文本HtmlDivElement的使用 HTML文本1.简单的Html属性设置:Bold、Font、FontSize、Color、下划线 示例如下: 2、获取Html文本的实际内容、获取html文本的实际宽高(contextWidth、contextHeight) 示例如下: 3、设置文本的水平居中对齐(align需要和width配合使用),换行( 换行需要有行高)、空格( ;) 【注意:目前不支持文本的垂直居中对齐,开发可以将(图片的高度-文本的高度)/2的值赋给文本的Y值,进行垂直居中对齐的替代设置】 示例如下: 4、实现超链接 示例如下: 5、实现html页面跳转 示例如下: 6、简单的图片显示 示例如下: 7、追加文本内容appendHtml 示例如下: 8、解决IOS手机上英文字母显示偏下的问题 在style样式中加垂直向上对齐valign:top属性 示例如下: 总结:以上的方法仅供参考,某些方法只是实现方式的一种,开发者也可以通过其他方式进行设置,如果有哪些方法没有涉及到的,欢迎开发者提出来,我们会陆续进行补充! 9.换行 设置style.width会自动换行,手动换行需要在span标签后添加br 10.描边 参考 HTMLDivElement文本字体描边怎么弄呢11.斜体 不支持 12.滚动条 参考 建议官方针对HtmlDIVElement出和TextArea相关的功能htmldivelement组件是没有滚动条的,它不具备输入功能,不能编辑,有点类似flash的htmltext文本可以实现富文本图文混排。textarea是支持滚动条的文本输入框,内容本身不能存在图片,不支持文本局部链接。 可以把htmldivelement放到一个容器里,然后把这个容器放到panel里,panel是支持滚动条的,这样可以通过内容的填充显示出滚动条! 13.参考示例