我有一个带文字突出显示的工作功能,问题是它还突出了换行符。见图:
以下是我用于突出显示的功能:
-(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]];
}
}
有没有简单的解决方案?我应该在换行前分割字符串并单独突出显示它们吗?另请注意,字符串可由用户编辑,因此必须有一些逻辑来检查文本在编辑其他部分时是否没有中断。
感谢您的任何建议。
答案 0 :(得分:2)
我的解决方案并不简单,我不知道它是否解决了你所有的问题,但我设法达到你想要的效果。
我在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
来实现这一点。
(当子串变得太长而无法适应线宽时,它会变为零)。
该方法返回每行的范围数组。 (范围将NSString
转换为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;
}
答案 1 :(得分:1)
基本上,我们需要检测换行符的范围,并将它们的属性设为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];
}