iOS_Swift运用AttributedString实现可点击文案

2022-07-20 14:30:18 浏览数 (1)

Swift项目中需要实现:一段文案默认最多显示3行,当超过三行时在末尾显示“更多”,当用户点击更多时,再展开显示所有文案:

期间遇到了一个类型转换的问题,在此记录说明一下:

代码语言:javascript复制
let attributedString = NSMutableAttributedString(string: "这是一段可点击的文字,后面还有很多文案更多",
                                                 attributes: [.foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 16)])

guard let range = attributedString.string.range(of: "更多") else { // Range<String.Index>?
  print("没有找到 更多 ")
  return
}
// 在这里我遇到了一个Error:
// Cannot convert value of type 'Range<String.Index>?' to specified type 'NSRange?' (aka 'Optional<_NSRange>')
// 就是上面guard那句 产生的range的类型是:Range<String.Index>?
// 而下面的addAttribute那句 添加.link的value需要的类型是:NSRange?
// 系统无法自动将其转换,所以我需要手动转一下:
// 可以根据 'Range<String.Index>?' 和 '完整字符串' 创建 NSRange?, 如下:
let convertedRange = NSRange(range, in: attributedString.string) // NSRange?
attributedString.addAttribute(.link, value: "more://", range: convertedRange) // NSRange?

let textView: UITextView = UITextView(frame: CGRect(x: 30, y: 100, width: 300, height: 100))
textView.backgroundColor = .cyan
textView.isEditable = false
textView.isScrollEnabled = false
textView.delegate = self // 指定代理处理点击方法
textView.attributedText = attributedString
view.addSubview(textView)

然后在代理方法里截获URL,并根据项目需求进行相应的处理:

代码语言:javascript复制
extension MOAttributedStringVC: UITextViewDelegate {
  func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
    if URL.absoluteString == "more://" {
      print("click more")
      return false
    }
    return true
  }
}

参考:

iOS 富文本添加点击事件

Ranges in Swift explained with code examples

0 人点赞