开篇点题,还是先骂两句产品经理,你%@!#@!……#@!&……#@!……!其实主要就是记录一下走的弯路,以便以后能够避开这些坑!首先说一下功能需求,产品经理原话就是模仿新浪微博实现一个话题功能,在发布的时候不需要可点击,只需要变色,显示的时候暂时实现变色,以后实现可点击!
实现可点击自然会想到coreText,如果只实现变色,就单纯使用AttributedString就可以了~~
首先自然是排除for循环去查找匹配,不管什么原因,反正看到用for循环查找就觉得蠢!然后就想到正则表达式!思路到这个地方都还是没有跑偏!
接下来就是到底要在哪个位置去设置我们的AttributedString。于是坑点就来了。
首先是想到UITextfield的delegate。
//即将开始编辑
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;
//开始编辑
- (void)textFieldDidBeginEditing:(UITextField *)textField;
//即将结束编辑
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField;
//结束编辑
- (void)textFieldDidEndEditing:(UITextField *)textField;
//编辑中
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
对着这几个代理看了半天,发现也只有最后一个像!要搞事情貌似只能放这儿里面!不得不承认,在这个地方耽误了不是一星半点的时间,因为之后在这里无论如何设置,都差点儿意思!话先说这儿。顺着思路接着搞,接下来就是将textfield.text里的话题内容搞出来!这里话就不多说了,正则表达式,前面讲到了,网上相关内容也一大把,百度,google自己看。
这里贴出代码
//通过正则表达式获取需要改变颜色的部分
+ (NSArray *)cutForAttributedStringWithMainString:(NSString *)str andPattern:(NSString *)pattern
{
NSString *searchText = str;
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];
NSArray * strArray = [regex matchesInString:searchText options:0 range:NSMakeRange(0, [searchText length])];
NSMutableArray * resArray = [NSMutableArray array];
for (NSTextCheckingResult* b in strArray)
{
NSString * resStr = [searchText substringWithRange:b.range];
[resArray addObject:resStr];
}
return [resArray copy];
}
//通过上面得到的变色字段数组,及所在的字符串,将话题字段提亮
+ (NSMutableAttributedString *)getSurplusStringByCutStringArray:(NSArray *)array andMainString:(NSString *)mainStr
{
NSMutableAttributedString *AttributedString = [[NSMutableAttributedString alloc] initWithString:mainStr];
for (int i = 0; i< array.count; i++) {
NSString * str = array[i];
NSRange range = [mainStr rangeOfString:str];
NSDictionary * AttributedStringDict = @{
//描述文字颜色
NSForegroundColorAttributeName : [UIColor blueColor] ,
//描述文字字体
NSFontAttributeName : [UIFont systemFontOfSize:15.0f],
//描述文字行距
NSBaselineOffsetAttributeName : [NSNumber numberWithFloat:0.0] ,
//描述文字间距
NSKernAttributeName : [NSNumber numberWithFloat:0.0]
};
[AttributedString addAttributes:AttributedStringDict range:range];
}
return AttributedString;
}
到这里,我们就获得了所需要的AttributedString了!
但是当我们将这段代码拿到UITextfield里去赋值的时候,我们发现,妈的!坑来了!
在UITextfield输入的时候,并不是我们键入什么,就是我们想要得到的字符,它是先预输入一段文字,这段文字是一个选中状态,而键盘上的ToolBar里才是我们想要得到的文字,我们想要的结果,恰恰也是结果文字,而不是包含这段选中状态的字符,代理里,无论是textfield还是string都会包含这段选中状态文字!于是我在这里就卡了很久,脑袋里就想着通过这个代理来搞定这段选中状态文字!
绕过这个坑,就看到希望了!如果我们直接忽略这个选中状态多好!如果我们能直接拿到didChange状态的文字岂不更美!
爬出这两个坑!就是最终结果!
1.首先拿到didChange!
[_textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
2.忽略选中状态的文字
- (void)textFieldDidChange:(UITextField *)textField
{
// 未选中状态文字范围
UITextRange *rang = textField.markedTextRange;
if (rang == nil) {
textField.attributedText = [YHAttributedStringTool getDisplayStringWithText:textField.text];
}
}
接下来还有一件事,就是在删除或者在文字中间加入编辑时会出现光标移位的情况,解决办法是给textField添加一个分类,增加一个像textView的selectedRange,用于记录富文本赋值前的光标位置记录,在赋值后设置其光标位置,关于这个分类网上很多,就不多说了,贴代码
- (void)textFieldDidChange:(UITextField *)textField
{
//记录光标位置
NSRange nowRange = _titleTextField.selectedRange;
_textFiledLocation = nowRange.location;
UITextRange *range = textField.markedTextRange; // 获取非=选中状态文字范围
if (range == nil) { // 没有非选中状态文字.就是确定的文字输入
textField.attributedText = [YHAttributedStringTool getDisplayStringWithText:textField.text];
}
//设置光标位置
textField.selectedRange = NSMakeRange(_textFiledLocation, 0);
}
网友评论