iOS UITextView如何实现类似微博的话题、提及用户效果(ios,uitextview,开发技术)

时间:2024-05-04 00:04:47 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

#话题#

最终效果是:

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

iOS UITextView如何实现类似微博的话题、提及用户效果

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

iOS UITextView如何实现类似微博的话题、提及用户效果

1.高亮

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

funcrefreshTopicStyle(){letregex=try!NSRegularExpression(pattern:"此处填写正则表达式",options:[NSRegularExpression.Options.caseInsensitive])//注意点lettotalRange=NSMakeRange(0,(inputTextView.attributedText.stringasNSString).length)letresults=regex.matches(in:inputTextView.attributedText.string,options:NSRegularExpression.MatchingOptions.init(rawValue:0),range:totalRange)letattributedString:NSMutableAttributedString=NSMutableAttributedString(string:inputTextView.attributedText.string)attributedString.setAttributes(normalAttributes,range:totalRange)forresultinresults{attributedString.setAttributes(topicAttributes,range:result.range)}inputTextView.attributedText=attributedString}

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

iOS UITextView如何实现类似微博的话题、提及用户效果

当然,也有一些其他办法来处理,如:

letlengthA=inputTextView.textStorage.lengthletlengthB=inputTextView.attributedText.string.utf16.count

2.点击事件

实现高亮部分的点击事件,目前有3种实现方案:

  • 直接给UITextView添加点击事件

  • 通过设置LinkAttribute,利用超文本链接的点击实现

  • 重写UITextViewtouches...方法

其中,第二种只限于在非编辑状态(即 textView.isEditable = false)下的点击,故排除,①、③均可,本文采用第一种,主要实现如下:

inputTextView.addTapGesture(self,handler:#selector(tapAttributedText(tap:)))@objcprivatefunctapAttributedText(tap:UITapGestureRecognizer){guardtap.isKind(of:UITapGestureRecognizer.self),lettextView=tap.viewas?UITextViewelse{return}letlayoutManager=textView.layoutManagervartapLocation=tap.location(in:textView)tapLocation.x-=textView.textContainerInset.lefttapLocation.y-=textView.textContainerInset.topletcharacterIndex=layoutManager.characterIndex(for:tapLocation,in:textView.textContainer,fractionOfDistanceBetweenInsertionPoints:nil)forresultingetCheckResult(format:Constants.TopicRegularExpression,text:inputTextView.attributedText.string){ifresult.range.location<characterIndex,characterIndex<result.range.location+result.range.length{//此处响应点击事件MBProgressHUD.showOnlyText(to:self.view,title:"美好时光")return}}inputTextView.becomeFirstResponder()}

@提及用户

  • 编辑过程中 @提及用户 实时高亮,且只允许选取的用户名高亮,手动输入不高亮;

iOS UITextView如何实现类似微博的话题、提及用户效果

  • 点击删除键的时候,一次性删除整个高亮部分

iOS UITextView如何实现类似微博的话题、提及用户效果

1.高亮

  • 记录位置

本来准备用正则匹配的,但因为只允许选取的用户名高亮,纯手动输入的不高亮,所以使用正则匹配就不合理了,这里采用实时记录、更新已选取用户名位置的方式实现。

///用来保存已选取用户信息的结构体structUserInfo{///用户名varuserName:String///位置信息varrange:NSRange///用于临时替换的等长字符串varplaceholder:String}
  • 临时替换

因为#话题#@提及用户可以同时存在,所以需要考虑可能互相影响的问题,比如@提及用户中间可能出现#,导致前后话题的正则匹配发生错乱。

解决方案是:先使用一个@开头且与@提及用户等长的字符串替换@提及用户,再执行#话题#的正则匹配,最后再换回来。

2.整体删除

删除操作分为两步:第一次点删除仅选中整个用户名(提醒用户是整体删除);第二次点删除才真的删除文本。

functextView(_textView:UITextView,shouldChangeTextInrange:NSRange,replacementTexttext:String)->Bool{iftext==""{for(num,user)inusersArray.enumerated(){//usersArray用于存放已选取的用户信息//②删除选中的用户名iftextView.selectedRange.location<=user.range.location&&NSMaxRange(user.range)<=NSMaxRange(textView.selectedRange){textView.replace(textView.selectedTextRange??UITextRange(),withText:"")returnfalse}//①选中用户名iftextView.selectedRange.length==0&&(textView.selectedRange.location==user.range.location+user.range.length){textView.selectedRange=user.rangereturnfalse}}}}
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:iOS UITextView如何实现类似微博的话题、提及用户效果的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Angular.JS中select下拉框如何设置value下一篇:

14 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18