实现富文本多个link点击.

  1. 方案一:通过实现 shouldInteractWithURL 代理方法,判断不同的URL进行事件响应。 缺点:长按有类似网页的copy复选菜单弹出。
  2. 方案二:重写touchesBegan事件,分别做selectRange设置,拿到selectionRects(for: aRange), 通过记录rect集合和content. 点击触碰,拿到点判断在哪个集合中。再block事件回调。
  3. 方案三:自定义tap事件,关闭canBecomeFirstResponder. 识别点击哪一个link进行响应事件。这里重点讲一下方案3。以下为草稿代码:
1.自定义textView子类
1
2
3
4
5
6
contentInset = .zero
textContainerInset = .zero
isEditable = false
isScrollEnable = false
isSelectable = false
isAccessibilityElement = true
2.tap事件
1
2
3
4
5
6
7
8
9
10
let tapLocation = tap.location(in: self) //点
let textPosition = closestPosition(to: tapLocation) //文本位置
let attributes = textStyling(at: textPosition, in: .backward) //拿到文本属性
if let _ = attributes[NSAttributeString.Key.underlineStyle] { //检查是否包含下划线
if let linkTag = attributes[NSAttributeString.Key.link] as? String {
let selectString = (linkTag == Const.firstLinkTag? “A” : “B”)
UIAccessibility.post(notification: .announcement, argument: selectString)
//block回调,做相关业务逻辑
}
}
3.使用:设置下划线和linkTag
1
2
3
4
let linkFirstText = LabelAgreementLinkTerms.localizableString()
If let range = customTextView.text.range(of: linkFirstText), let nsRange = customTextView.text.nsRange(from: range) {
customTextView.setUnderlineTextWith(nsRange, underlineColor: color, linkTag: Const.firstLinkTag)
}

关于设置Accessibility

试错: 之前一开始想通过触摸点来做,但发现在voiceOver情况下,tap.location拿到的点不对。经过查找资料,需要设置 accessibilityTraits = .allowDirectInteraction 才能正常拿到对应的点。但这违背了Accessible的初衷,用户在视弱的情况下,并不一定能准确触碰到点,而是直接触碰屏幕任何一个地方。
最后方案:通过设置accessibilityTraits = .link告知用户这是个链接,并同时设置customeActions. 并同时可支持 Accessibility的voiceOver和SwitchControl, 通过CustomAction的Tag标识点击了谁。

textView 加载 html 富文本

多数情况下,textView也会用在一些短小的富文本显示上,如果hmtl标签不是很复杂的情况下可以用textView来展示,对链接点击事件也提供了很方便的支持。如下。

1
2
NSAttributedString * attrStr = [[NSAttributedString alloc] initWithData:[str dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
textView.attributeText = attrStr

但在一些html比较复杂的情况下,比如使用table表情以及各种嵌套的情况下,可以直接使用WKWebView来展示。
1
2
3
4
guard let conents = try? String(contentOf: pathURL, encoding: String.Encoding.utf8) else {
return
}
webview.loadHtmlString(contents, baseURL: nil);

系统辅助功能 -> 改变字体大小

当在系统设置-> 辅助功能设置 调整字体大小时候,textView的富文本如何自动跟着变化呢?Label需要设置adjustsFontForContentSizeCategory为true即可,textView如果设置了attributeString,则需要添加UIContentSizeCategory.didChangeNotification的通知, 拿到font的size变化,重新更新一下attributeKey为font的值。以下伪代码。

1
2
3
let pointSize = font.fontDescriptor.pointSize
let changedFont = font.withSize(pointSize)
textView.addAttribute(value:changedFont forKey:AttributeKey.font)

textView实现富文本编辑

textView实现富文本编辑

优秀开源库推荐: 第三方框架YYKit -> YYTextView

评论