// // UMComEditTextView.m // UMCommunity // // Created by umeng on 15/11/11. // Copyright © 2015年 Umeng. All rights reserved. // #import "UMComEditTextView.h" #import "UMComResouceDefines.h" #import #import "UMComMutiTextRun.h" #import #import @interface UMComEditTextView () @property (nonatomic, strong) UILabel *noticeLabel; @property (nonatomic, strong) NSMutableArray *regularExpressionArray; @end @implementation UMComEditTextView { BOOL isShowTopicNoticeBgView; } - (instancetype)initWithFrame:(CGRect)frame { self = [self initWithFrame:frame checkWords:nil regularExStrArray:nil]; if (self) { } return self; } - (instancetype)initWithFrame:(CGRect)frame checkWords:(NSArray *)checkWords regularExStrArray:(NSArray *)regularExStrArray { if (UMSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7")) { NSTextContainer *container = [[NSTextContainer alloc] initWithSize:CGSizeMake(frame.size.width, frame.size.height)]; container.lineFragmentPadding = 2; container.size = CGSizeMake(self.frame.size.width, MAXFLOAT);//设置成最大得高度输入多文本滚动 container.widthTracksTextView = YES; NSTextStorage *textStorage = [[NSTextStorage alloc]init]; NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init]; [layoutManager addTextContainer:container]; [textStorage addLayoutManager:layoutManager]; self = [super initWithFrame:frame textContainer:container]; //如果有话题则默认添加话题 }else{ self = [super initWithFrame:frame]; } if (self) { _regularExpressionArray = [NSMutableArray arrayWithCapacity:regularExStrArray.count]; for (NSString *regex in regularExStrArray) { NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:regex options:NSRegularExpressionCaseInsensitive error:nil]; if (regularExpression) { [_regularExpressionArray addObject:regularExpression]; } } self.textColor= [UIColor blackColor]; self.font = [UIFont systemFontOfSize:20]; self.delegate = self; self.checkWords = checkWords; _noticeLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)]; //_noticeLabel.backgroundColor = [UIColor clearColor]; _noticeLabel.font = UMComFontNotoSansLightWithSafeSize(14); _noticeLabel.text = UMComLocalizedString(@"um_com_contentTooLong", @"抱歉,内容过长"); _noticeLabel.textAlignment = NSTextAlignmentCenter; _noticeLabel.textColor = [UIColor blueColor]; _noticeLabel.backgroundColor = [UIColor lightGrayColor]; _noticeLabel.hidden = YES; [self addSubview:_noticeLabel]; _placeholderLabel = [[UILabel alloc]initWithFrame:CGRectMake(5, -5, frame.size.width, 40)]; _placeholderLabel.font = UMComFontNotoSansLightWithSafeSize(15); _placeholderLabel.backgroundColor = [UIColor clearColor]; _placeholderLabel.textColor = [UIColor grayColor]; [self addSubview:_placeholderLabel]; _maxTextLenght = 1000; } return self; } - (void)updateEditTextView { [self textViewDidChange:self]; [self matchWordsWithTextColor:UMComColorWithHexString(FontColorBlue)]; } #pragma mark - UITextViewDelegate - (void)textViewDidChangeSelection:(UITextView *)textView { [self showPlaceHolderLabelWithTextView:textView]; if (self.editDelegate && [self.editDelegate respondsToSelector:@selector(editTextViewDidChangeSelection:)]) { [self.editDelegate editTextViewDidChangeSelection:self]; } } - (BOOL)textViewShouldEndEditing:(UITextView *)textView { return YES; } - (void)showPlaceHolderLabelWithTextView:(UITextView *)textView { if (textView.text.length > 0 && ![@" " isEqualToString:textView.text]) { self.placeholderLabel.hidden = YES; }else{ self.placeholderLabel.hidden = NO; } } - (void)textViewDidEndEditing:(UITextView *)textView { if (textView.text.length == 0) { self.placeholderLabel.hidden = NO; } if (UMSYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(@"6")) { [self matchWordsWithTextColor:UMComColorWithHexString(FontColorBlue)]; } if (self.editDelegate && [self.editDelegate respondsToSelector:@selector(editTextViewDidEndEditing:)]) { [self.editDelegate editTextViewDidEndEditing:self]; } } - (void)hiddenTextView { self.noticeLabel.hidden = YES; } -(void) doShowPlaceHolderLabel { self.noticeLabel.hidden = NO; //显示noticeLabel的位置 self.noticeLabel.frame = CGRectMake(self.contentOffset.x,self.contentOffset.y, self.bounds.size.width, self.bounds.size.height); [self performSelector:@selector(hiddenTextView) withObject:nil afterDelay:0.8f]; } - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { //判断text的长度大于零,避免删除的情况不能编辑 //if ([self getRealTextLength] > self.maxTextLenght && text.length > 0) { if (self.maxTextLenght <= 0) { return NO; } //当时删除的时候text为空,以此方法判断是否用户点击删除按键 if ([text isEqualToString:@""]) { return YES; } NSInteger markLength = 0;//标记的长度 UITextRange* curMarkText = textView.markedTextRange; if (curMarkText) { markLength = [self offsetFromPosition:curMarkText.start toPosition:curMarkText.end]; } NSInteger curLength = 0.f; NSInteger nextLength = 0.f; curLength = [UMComKit getStringLengthWithString:self.text];//当前长度(用于判断表情) nextLength = [UMComKit getStringLengthWithString:text];//即将要输入的长度(用于判断表情) curLength -= markLength; if (curLength + nextLength > self.maxTextLenght ) { self.noticeLabel.hidden = NO; //显示noticeLabel的位置 self.noticeLabel.frame = CGRectMake(self.contentOffset.x,self.contentOffset.y, self.bounds.size.width, self.bounds.size.height); [self performSelector:@selector(hiddenTextView) withObject:nil afterDelay:0.8f]; return NO; }else{ self.noticeLabel.hidden = YES; } if (self.editDelegate && [self.editDelegate respondsToSelector:@selector(editTextView:shouldChangeTextInRange:replacementText:complection:)]) { __weak typeof(self) weakSelf = self; return [self.editDelegate editTextView:self shouldChangeTextInRange:range replacementText:text complection:^{ [weakSelf textViewDidChange:weakSelf]; }]; } return YES; } - (void)textViewDidChange:(UITextView *)textView { if (UMSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7")) { [self matchWordsWithTextColor:UMComColorWithHexString(FontColorBlue)]; } [self showPlaceHolderLabelWithTextView:textView]; //http://stackoverflow.com/questions/19948394/textviewdidchange-crashes-in-ios-7 if (textView.markedTextRange) { //联想输入的时候,不需要计算其长度 return; } //此处判断是否达到最大长度限制 NSInteger curLength = [UMComKit getStringLengthWithString:self.text];//当前长度(用于判断表情) if (curLength > self.maxTextLenght && self.maxTextLenght > 0) { [self doShowPlaceHolderLabel]; self.text = [self.text substringToIndex:self.maxTextLenght]; } } #pragma mark - textUpdata - (void)matchWordsWithTextColor:(UIColor *)color { if (self.text.length == 0) { return; } if (self.getCheckWords) { self.checkWords = self.getCheckWords(); } __weak typeof(self) weakSelf = self; if (UMSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7")) { [self updateiOS7AndLaterTextWithColor:color checkWords:self.checkWords completion:^(NSArray *matchWords) { if (weakSelf.editDelegate && [weakSelf.editDelegate respondsToSelector:@selector(editTextViewDidUpdate:matchWords:)]) { weakSelf.checkWords = [weakSelf.editDelegate editTextViewDidUpdate:weakSelf matchWords:[matchWords valueForKeyPath:@"text"]]; } }]; }else{ [self creatHighLightWithFont:self.font color:color checkWords:self.checkWords complection:^(NSArray * matchWords, NSMutableAttributedString *attributedString) { if (self.editDelegate && [self.editDelegate respondsToSelector:@selector(editTextViewDidUpdate:matchWords:)]) { [self.editDelegate editTextViewDidUpdate:weakSelf matchWords:[matchWords valueForKeyPath:@"text"]]; } weakSelf.attributedText = attributedString; }]; } [self reloadInputViews]; } - (NSArray *)rangeArrayOfSubString:(NSString *)subString originStrin:(NSString *)originString lastRangeArray:(NSArray *)lastRangeArray { if (originString.length >= subString.length) { NSMutableArray *rangeArray = [NSMutableArray array]; if (lastRangeArray.count > 0) { [rangeArray addObjectsFromArray:lastRangeArray]; } NSRange macthRange = [originString rangeOfString:subString]; if (macthRange.length > 0) { NSValue *rangeValue = [NSValue valueWithRange:macthRange]; [rangeArray addObject:rangeValue]; [self rangeArrayOfSubString:subString originStrin:[originString substringFromIndex:macthRange.length - 1] lastRangeArray:rangeArray]; } return rangeArray; } return lastRangeArray; } - (void)updateiOS7AndLaterTextWithColor:(UIColor *)color checkWords:(NSArray *)checkWords completion:(void (^) (NSArray *matchWords))block { [self.textStorage addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, self.textStorage.length)]; NSMutableArray *HLTextUnits = [NSMutableArray array]; for (NSString *checkWord in checkWords) { NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:checkWord options:NSRegularExpressionDotMatchesLineSeparators error:nil]; NSArray *matchs = [regular matchesInString:self.textStorage.string options:0 range:NSMakeRange(0, [self.textStorage.string length])]; for (NSTextCheckingResult *match in matchs) { [self.textStorage addAttribute:NSForegroundColorAttributeName value:color range:match.range]; if (![[HLTextUnits valueForKeyPath:@"text"] containsObject:checkWord]) { UMComHighLightTextUnit *textUnit = [UMComHighLightTextUnit textUnitWithText:checkWord font:self.font textColor:color range:match.range]; [HLTextUnits addObject:textUnit]; } } } if (block) { block(HLTextUnits); } } //产生高亮字体 - (void)creatHighLightWithFont:(UIFont *)font color:(UIColor *)color checkWords:(NSArray *)checkWords complection:(void(^)(NSArray *checkWords ,NSMutableAttributedString *attributedString))block { if (self.text.length == 0) { return; } NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]initWithString:self.text]; self.attributedText = attributedString; [attributedString addAttribute:NSForegroundColorAttributeName value:(id)[UIColor blackColor] range:NSMakeRange(0, attributedString.length-1)]; NSString *string = attributedString.string; NSMutableArray *HLTextUnits = [NSMutableArray array]; for (NSRegularExpression *regularExpression in _regularExpressionArray) { NSArray *matchs = [regularExpression matchesInString:string options:0 range:NSMakeRange(0, string.length)]; if ([regularExpression.pattern isEqualToString:UrlRelerSring]) { for (NSTextCheckingResult *match in matchs) { NSString* matchText = [self.textStorage.string substringWithRange:match.range]; [attributedString addAttribute:(id)NSForegroundColorAttributeName value:(id)color range:match.range]; if (![[HLTextUnits valueForKeyPath:@"text"] containsObject:matchText]) { UMComHighLightTextUnit *textUnit = [UMComHighLightTextUnit textUnitWithText:matchText font:self.font textColor:color range:match.range]; [HLTextUnits addObject:textUnit]; } } }else{ for (NSTextCheckingResult *match in matchs) { NSRange matchRange = NSMakeRange(match.range.location, match.range.length); NSString *matchText = [string substringWithRange:matchRange]; for (NSString *checkWord in checkWords) { if ([matchText isEqualToString:checkWord]) { [attributedString addAttribute:(id)NSForegroundColorAttributeName value:(id)color range:match.range]; if (![[HLTextUnits valueForKeyPath:@"text"] containsObject:matchText]) { UMComHighLightTextUnit *textUnit = [UMComHighLightTextUnit textUnitWithText:matchText font:self.font textColor:color range:match.range]; [HLTextUnits addObject:textUnit]; } } } } } } [attributedString addAttribute:NSFontAttributeName value:(id)font range:NSMakeRange(0, attributedString.length)]; if (block) { block(HLTextUnits, attributedString); } } - (NSInteger)getRealTextLength { NSInteger topicAndUserLength = 0; NSMutableArray *matchs = [NSMutableArray array]; for (NSRegularExpression *regularExpression in _regularExpressionArray) { NSArray *subMatchs = [regularExpression matchesInString:self.text options:0 range:NSMakeRange(0, self.text.length)]; if (subMatchs.count > 0) { [matchs addObjectsFromArray:subMatchs]; } } NSArray *checkWords = self.checkWords; for (NSTextCheckingResult *match in matchs) { for (NSString *item in checkWords) { NSRange matchRange = NSMakeRange(match.range.location, match.range.length); NSString *matchText = [self.text substringWithRange:matchRange]; if ([item isEqualToString:matchText]) { topicAndUserLength += [UMComKit getStringLengthWithString:matchText]; } } } NSString *realTextString = [self.text stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]; NSInteger realTextLength = [UMComKit getStringLengthWithString:realTextString] - topicAndUserLength; return realTextLength; } /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ -(BOOL)checkMaxLength:(NSString*)text { if (!text) { return NO; } NSInteger curLength = [UMComKit getStringLengthWithString:text]; if (curLength> self.maxTextLenght ) { self.noticeLabel.hidden = NO; //显示noticeLabel的位置 self.noticeLabel.frame = CGRectMake(self.contentOffset.x,self.contentOffset.y, self.bounds.size.width, self.bounds.size.height); [self performSelector:@selector(hiddenTextView) withObject:nil afterDelay:0.8f]; return YES; } else{ return NO; } } @end @implementation UMComHighLightTextUnit - (instancetype)initWithTextUnitWithText:(NSString *)text font:(UIFont *)font textColor:(UIColor *)color range:(NSRange)range { self = [super init]; if (self) { self.text = text; self.textColor = color; self.font = font; self.range = range; } return self; } + (UMComHighLightTextUnit *)textUnitWithText:(NSString *)text font:(UIFont *)font textColor:(UIColor *)color range:(NSRange)range { UMComHighLightTextUnit *textUnit = [[UMComHighLightTextUnit alloc]initWithTextUnitWithText:text font:font textColor:color range:range]; return textUnit; } @end