UITextView – 使用NSBackgroundColor突出显示文本 – 排除换行符

我有一个带文本高亮的工作function,问题是它还突出了换行符。 看图像:

在此处输入图像描述

以下是我用于突出显示的function:

-(void)setHighlight{ //set highlighted __block BOOL textIsHighlited = YES; [self.attributedText enumerateAttributesInRange:[self selectedRange] options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) { if ([attrs valueForKey:@"NSBackgroundColor"] == Nil) { textIsHighlited = NO; } }]; if (textIsHighlited) { [self.textStorage removeAttribute:NSBackgroundColorAttributeName range:[self selectedRange]]; }else{ [self.textStorage addAttribute:NSBackgroundColorAttributeName value:[UIColor greenColor] range:[self selectedRange]]; } } 

有没有简单的解决方案? 我应该在换行前分割字符串并单独突出显示它们吗? 另请注意,字符串可由用户编辑,因此必须有一些逻辑来检查文本在编辑其他部分时是否没有中断。

谢谢你的任何建议。

我的解决方案并不简单,我不知道它是否解决了你所有的问题,但我设法达到你想要的效果。

我在UILabel上测试了它,使用不同的字体和字体大小,效果很好。

在这里我做了什么:

 - (NSArray*)getRangesOfLinesForText:(NSString*)text font:(UIFont*)font containerWidth:(float)width { NSMutableArray *ranges = [[NSMutableArray alloc] init]; NSInteger lastWhiteSpaceIndex = 0; NSInteger rangeStart = 0; NSMutableString *substring = [[NSMutableString alloc] init]; for (int i = 0; i < [text length]; i++) { char c = [text characterAtIndex:i]; [substring appendFormat:@"%c",c]; CGRect substringRect = [substring boundingRectWithSize:CGSizeMake(width, font.capHeight)options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil]; if([[NSCharacterSet whitespaceAndNewlineCharacterSet] characterIsMember:c]) { lastWhiteSpaceIndex = i; } if(substringRect.size.width == 0) { NSRange range; if (lastWhiteSpaceIndex != i) { range = NSMakeRange(rangeStart, lastWhiteSpaceIndex-rangeStart); [ranges addObject:NSStringFromRange(range)]; substring = [[NSMutableString alloc] init]; i = lastWhiteSpaceIndex; rangeStart = lastWhiteSpaceIndex+1; } } } //Last Line NSRange range = NSMakeRange(rangeStart, [text length]-rangeStart); [ranges addObject:NSStringFromRange(range)]; return ranges; } 

上面的方法将text字符串拆分为单独的行。 不幸的是,方法boundingRectWithSize:options:attributes:context:不支持换行换行,所以我必须自己检测它。 我通过检查substringRect.size.width == 0来实现这一点。 (当子串变得太长而无法适应线宽时,它会变为零)。

该方法返回每行的范围数组。 (使用NSStringFromRange将范围转换为NSStringFromRange )。

使用示例:

 - (void)viewDidLoad { [super viewDidLoad]; UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectFromString(@"{{0,0},{300,400}}")]; textLabel.numberOfLines = 0; [self.view addSubview:textLabel]; NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec luctus quis sapien a rutrum. Vivamus nec leo suscipit nibh rutrum dignissim at vel justo. Maecenas mi orci, ultrices non luctus nec, aliquet et nunc."; NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:text]; for (NSString* stringRange in [self getRangesOfLinesForText:text font:textLabel.font containerWidth:textLabel.frame.size.width]) { [string addAttribute:NSBackgroundColorAttributeName value:[UIColor greenColor] range:NSRangeFromString(stringRange)]; } textLabel.attributedText = string; } 

请参阅TextViewHighlighter

基本上,我们需要检测换行符的范围,并将它们的属性设置为NSBackgroundColorAttributeName: [UIColor clearColor]

 NSMutableAttributedString *highlighedAttributedString = [[NSMutableAttributedString alloc] initWithString:self.text]; [highlighedAttributedString addAttributes:@{NSForegroundColorAttributeName: self.textColor, NSBackgroundColorAttributeName: self.highlightedColor } range:NSMakeRange(0, self.text.length)]; for (NSValue *rangeValue in rangeValues) { NSRange range = [rangeValue rangeValue]; [highlighedAttributedString addAttributes:@{NSBackgroundColorAttributeName: [UIColor clearColor], } range:range]; }