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

时间:2014-04-19 10:53:03

标签: ios objective-c uitextview textkit

我有一个带文字突出显示的工作功能,问题是它还突出了换行符。见图:

enter image description here

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

   -(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]];
        }
    }

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

感谢您的任何建议。

2 个答案:

答案 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)

请参阅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];
    }