最近接了一个需求,在发布动态的时候,增加类似微博的#话题#、@提及用户的效果,在此做一简要记录。

话题

最终效果是:

编辑过程中#话题内容#实时高亮

高亮部分可以响应点击事件

1.高亮
基本思路是:使用正则匹配出成对的#,再利用UITextView的富文本实现高亮效果。
func refreshTopicStyle() {

  1. let regex = try! NSRegularExpression(pattern: "此处填写正则表达式",
  2. options:[NSRegularExpression.Options.caseInsensitive])
  3. // 注意点
  4. let totalRange = NSMakeRange(0, (inputTextView.attributedText.string as NSString).length)
  5. let results = regex.matches(in: inputTextView.attributedText.string,
  6. options: NSRegularExpression.MatchingOptions.init(rawValue: 0),
  7. range: totalRange)
  8. let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: inputTextView.attributedText.string)
  9. attributedString.setAttributes(normalAttributes, range: totalRange)
  10. for result in results {
  11. attributedString.setAttributes(topicAttributes, range: result.range)
  12. }
  13. inputTextView.attributedText = attributedString
  14. }

这有一个注意点,计算 totalRange 前,先将 String 转成了 NSString,这是因为此处 NSRange 中的 length 需要的是 UTF-16 长度,也就是与 NSString 的 length 定义一致,而 Swift 中的 String 没有 length 只有 count,指的是字符数,当文本中出现 emoji 表情时,二者就不一致了。

当然,也有一些其他办法来处理,如:
let lengthA = inputTextView.textStorage.length
let lengthB = inputTextView.attributedText.string.utf16.count
2.点击事件
实现高亮部分的点击事件,目前有3种实现方案:

直接给UITextView添加点击事件
通过设置LinkAttribute,利用超文本链接的点击实现
重写UITextView的touches…方法
其中,第二种只限于在非编辑状态(即 textView.isEditable = false)下的点击,故排除,①、③均可,本文采用第一种,主要实现如下:
inputTextView.addTapGesture(self, handler: #selector(tapAttributedText(tap:)))
@objc private func tapAttributedText(tap: UITapGestureRecognizer) {
guard tap.isKind(of: UITapGestureRecognizer.self), let textView = tap.view as? UITextView else {
return
}
let layoutManager = textView.layoutManager
var tapLocation = tap.location(in: textView)
tapLocation.x -= textView.textContainerInset.left
tapLocation.y -= textView.textContainerInset.top
let characterIndex = layoutManager.characterIndex(for: tapLocation,
in: textView.textContainer,
fractionOfDistanceBetweenInsertionPoints: nil)
for result in getCheckResult(format: Constants.TopicRegularExpression, text: inputTextView.attributedText.string) {
if result.range.location < characterIndex, characterIndex < result.range.location + result.range.length {
// 此处响应点击事件
MBProgressHUD.showOnlyText(to: self.view, title: “美好时光”)
return
}
}
inputTextView.becomeFirstResponder()
}``

更多相关文章

  1. android 7.0平台客制化虚拟导航按键(隐藏NavigationBar,上滑显示N
  2. 修改Android(安卓)Studio的Android(安卓)SDK Path
  3. 【读书笔记】Android(安卓)输入系统
  4. 浅谈Android事件分发机制
  5. 关于listview的item中如果有textview,listview点击item没有效果的
  6. Android(安卓)水波纹点击效果(Ripple Effect)
  7. 第3.3.1节 处理手势操作
  8. Activity的launchMode相关
  9. Android(安卓)Touch事件分发机制详解之由点击引发的战争

随机推荐

  1. System Permissions—— android系统权限
  2. PC和Android(安卓)adb通信
  3. linaro pandaboard android 编译kernel
  4. 手把手叫你用android 调研web services
  5. 【Android 基础7.1 7.2】AsyncTask & Asy
  6. android Draw
  7. Android Interface Definition Language
  8. Android的Face++Demo错误1302
  9. android CrashHandler
  10. Android(安卓)保存图片到本地