项目开发时,用到了这样一个功能,类似于微博的话题,用户点击的时候,需要插入关键词文本到textView中,并显示成红色,当用户输入的时候,就是黑色字体;
即,两个[]之间的字体为红色。
最终实现效果:
首先,要想实现这种效果,最先想到的是使用富文本NSMutableAttributedString将[]范围内的文字修改为红色;
1>使用正则表达式,匹配所有[]范围的文字的range,将所有[]范围内的文字改为红色;
2>将修改完的文字赋值给textView,修改textView的光标位置;
// 找到所有的关键词,并修改颜色
- (void)findAllKeywordsChangeColor:(UITextView *)textView {
NSString *string = textView.text;
// 记录光标位置
NSRange rangeDefault = textView.selectedRange;
NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString: string];
[attrStr addAttribute:NSForegroundColorAttributeName value:COLOR102 range: NSMakeRange(0, string.length)];
NSString *pattern = @"\\[(.*?)\\]";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options: NSRegularExpressionCaseInsensitive error:nil];
// 匹配所有项
NSArray *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)];
NSLog(@"matches ==== %@",matches);
//
for (int i = 0; i < matches.count; i++) {
NSTextCheckingResult *result = matches[i];
NSRange range = [result rangeAtIndex:0];
NSLog(@"查找合适的位置location:%lu-----%lu",range.location,range.length);
NSString *subStr = [attrStr.string substringWithRange:range];
NSUInteger length = subStr.length;
[attrStr addAttribute:NSForegroundColorAttributeName value:kXZMainBgColor range:NSMakeRange(range.location, length)];
}
[attrStr addAttribute:NSFontAttributeName value:self.textEdit.font range:NSMakeRange(0, string.length)];
self.textEdit.attributedText = attrStr;
// 恢复光标位置
NSRange rangeNow = NSMakeRange(rangeDefault.location, 0);
textView.selectedRange = rangeNow;
}
需要注意的是:在textView中,当输入文字的时候,下一个文字的颜色和字体等属性,是跟随前一个文字的颜色和字体属性进行设置的,所以,在修改完颜色之后,要统一设置一遍textView的文字的字体大小:
[attrStr addAttribute:NSFontAttributeName value:self.textEdit.font range:NSMakeRange(0, string.length)];
实现是可以了,但是,现在是在哪个方法实现这种效果呢,当输入文字的文字改变的时候进行修改,所以就在textViewDidChange代理方法中实现效果。
当我运行查看效果的时候,发现是如下的效果:
在键盘上拼拼音的时候,还没有拼好,拼音就已经进入了输入框,原因是:当我们在拼拼音的时候,textViewDidChange代理方法也是在执行的,只要执行就会把值赋给textView,所以就显示出来了。
解决这个问题的思路是:找到一个点,刚好我拼完拼音,写入的时候,再进行修改和赋值。查找资料发现textView还有联想词这一说法,就是在中文输入的时候,当拼拼音的时候,把一些可能的结果高亮展示出来,所以,我们就在改变颜色赋值之前需要做个判断,判断当前是否联想词的高亮状态,将代码修改为如下:
- (void)textViewDidChange:(UITextView *)textView {
UITextRange *selectedRange = [textView markedTextRange];
// 获取高亮字符的位置
UITextPosition *position = [textView positionFromPosition:selectedRange.start offset:0];
// 如果没有高亮字符,修改颜色赋值
if (!position) {
[self findAllKeywordsChangeColor:textView];
}
}