如何为NSAttributedString添加target以实现UITextView中的可点击文本
实现UITextView中AttributedString可点击效果的方案
优先推荐使用系统原生支持的link属性方案,适配性更高,实现成本更低。
方案1:系统link属性实现(推荐)
该方案利用UITextView原生支持的链接识别能力,无需自定义手势,适配iOS 7+所有系统版本。
- 第一步:构造包含可点击片段的富文本,给要点击的字符串添加
link属性,值使用自定义scheme的URL方便识别动作
// 拼接原有文本和可点击文本 let fullContent = NSMutableAttributedString(string: "原有内置的段落文本内容 ") let clickStr = NSAttributedString( string: "点击查看更多", attributes: [ .link: URL(string: "customAction://showMore")! ] ) fullContent.append(clickStr) // 赋值给UITextView textView.attributedText = fullContent // 必须配置的两个属性,否则交互无法触发 textView.isEditable = false textView.isSelectable = true // 自定义链接的显示样式 textView.linkTextAttributes = [ .foregroundColor: UIColor.blue, .underlineStyle: NSUnderlineStyle.single.rawValue ] // 设置代理 textView.delegate = self
- 第二步:实现UITextViewDelegate方法,拦截链接点击执行自定义逻辑
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { // 匹配我们自定义的动作scheme if URL.scheme == "customAction" { switch URL.host { case "showMore": // 此处写你的点击触发逻辑 print("可点击文本被触发") default: break } // 返回false阻止系统默认打开URL的行为 return false } // 其他正常链接返回true交给系统处理 return true }
方案2:自定义属性+点击识别(灵活度更高)
如果需要完全自定义点击逻辑、不使用系统链接样式,可以通过自定义富文本属性加点击手势识别实现。
- 第一步:给可点击文本添加自定义属性标记
let customActionKey = NSAttributedString.Key("CustomClickAction") let fullContent = NSMutableAttributedString(string: "原有内置的段落文本内容 ") let clickStr = NSAttributedString( string: "点击查看更多", attributes: [ .foregroundColor: UIColor.green, customActionKey: "showMore" ] ) fullContent.append(clickStr) textView.attributedText = fullContent textView.isEditable = false textView.isSelectable = true
- 第二步:给UITextView添加点击手势,识别点击位置的文本属性
// 添加点击手势 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTextViewTap(_:))) textView.addGestureRecognizer(tapGesture) @objc func handleTextViewTap(_ gesture: UITapGestureRecognizer) { let textView = gesture.view as! UITextView let location = gesture.location(in: textView) // 获取点击位置对应的字符索引 guard let charIndex = textView.layoutManager.characterIndex( for: location, in: textView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil ) else { return } // 检查该位置的字符是否有我们自定义的属性 let customActionKey = NSAttributedString.Key("CustomClickAction") if charIndex < textView.attributedText.length { let attributes = textView.attributedText.attributes(at: charIndex, effectiveRange: nil) if let actionName = attributes[customActionKey] as? String { if actionName == "showMore" { // 执行点击逻辑 print("可点击文本被触发") } } } }
注意事项
- 两个方案都必须保证
isEditable = false、isSelectable = true,缺少任意一个属性都会导致点击无法触发 - 方案1的系统link样式可以通过
linkTextAttributes完全自定义,不需要使用系统默认的蓝色下划线样式 - 如果不需要UITextView的文本选择功能,可以自定义手势屏蔽选择行为,只保留点击识别能力
内容的提问来源于stack exchange,提问作者aFella
相关产品推荐
相关产品推荐

