突出显示UILabel中的文本 [英] Highlight just the text in a UILabel

查看:81
本文介绍了突出显示UILabel中的文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试设置背景颜色/突出显示 UILabel 中的文本。问题是为了保持文本居中,添加到 UILabel 的换行符和空格也被突出显示。

I'm attempting to set the background color/highlight just the text within a UILabel. The issue is that the line breaks and spaces added to the UILabel to keep the text centered are also being highlighted.

注意之前的间距突出显示 UILabel 中的最后一行。此外,任何新行的开头和结尾也会突出显示。

Notice the spacing before the last line in the UILabel is highlighted. Also, the beginning and end of any new lines are also highlighted.

我正在使用以下代码创建上面的示例:

I'm creating the example above with the following code:

-(void)createSomeLabel {
    // Create and position my label
    UILabel *someLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,
                                                                   0,
                                                                   self.view.frame.size.width - 40,
                                                                   self.view.frame.size.height - 300)];
    someLabel.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
    someLabel.textAlignment = NSTextAlignmentCenter;
    someLabel.textColor = [UIColor whiteColor];
    someLabel.lineBreakMode = NSLineBreakByWordWrapping;
    someLabel.numberOfLines = 0;
    [self.view addSubview:someLabel];

    // This string will be different lengths all the time
    NSString *someLongString = @"Here is a really long amount of text that is going to wordwrap/line break and I don't want to highlight the spacing. I want to just highlight the words and a single space before/after the word";

    // Create attributed string
    NSMutableAttributedString *someLongStringAttr=[[NSMutableAttributedString alloc] initWithString:someLongString attributes:nil];

    // Apply background color
    [someLongStringAttr addAttribute:NSBackgroundColorAttributeName
                      value:[UIColor colorWithWhite:0 alpha:0.25]
                      range:NSMakeRange(0, someLongStringAttr.length)];

    // Set text of label
    someLabel.attributedText = someLongStringAttr;
}

我想要实现的输出是如果只有一个空格,则仅突出显示文本和单词之间的空格。文本的长度和 UILabel 的大小将不断变化,因此不幸的是,难以编写解决方案。

The output I'd like to achieve is to highlight only the text and the spaces between the words if there is only one space. The length of the text and the size of the UILabel will constantly be different so hard coding a solution is not an option unfortunately.

推荐答案

在我看来,换行是问题所在。
我的想法是尝试知道UILabel何时添加换行符,然后从突出显示的字符范围中删除该字符。

It seemed to me that the line break was the problem. My idea was to try and know when the UILabel would add a line break and then just remove that character from the range of characters being highlighted.

它出现您不能只询问UILabel换行的位置,但是当您将NSString添加到标签时,可以检查NSString的大小。
使用这些信息,您可以不断检查每个角色的高度,当高度发生变化时,您知道自己有了一条新线。

It appears that you can't just ask UILabel where the line breaks are going to be but you can check what the size of an NSString will be when you add it to a label. Using this information you can increment through each character constantly checking the height, and when the height changes you know you have a new line.

我做了一个获取Label的字符串并将其分隔为将出现在UILabel中的各个行的示例。一旦我有了每一行,我只需在每一行设置背景颜色而不是整个字符串。这消除了在换行符上设置的背景颜色。

I have made an example that takes the Label's string and separates it into its individual lines that will appear in the UILabel. Once I have each line, I just set the background color on each line instead of the whole string. This eliminates and background colors being set on line breaks.

可能有更好的解决方案,这个可能会针对更好的性能进行优化,但这是一个起点,它似乎有效。

There are probably better solutions, and this one could probably be optimized for better performance, but it's a starting point and it appears to work.

- (void)createSomeLabel {
    // Create and position my label
    UILabel *someLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,
                                                                   0,
                                                                   self.view.frame.size.width - 40,
                                                                   self.view.frame.size.height - 300)];
    someLabel.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
    someLabel.textAlignment = NSTextAlignmentCenter;
    someLabel.textColor = [UIColor whiteColor];
    someLabel.lineBreakMode = NSLineBreakByWordWrapping;
    someLabel.numberOfLines = 0;
    [self.view addSubview:someLabel];

    // This string will be different lengths all the time
    NSString *someLongString = @"Here is a really long amount of text that is going to wordwrap/line break and I don't want to highlight the spacing. I want to just highlight the words and a single space before/after the word";

    // Create attributed string
    NSMutableAttributedString *someLongStringAttr=[[NSMutableAttributedString alloc] initWithString:someLongString attributes:nil];


    // The idea here is to figure out where the UILabel would automatically make a line break and get each line of text separately.
    // Temporarily set the label to be that string so that we can guess where the UILabel naturally puts its line breaks.
    [someLabel setText:someLongString];
    // Get an array of each individual line as the UILabel would present it.
    NSArray *allLines = getLinesForLabel(someLabel);
    [someLabel setText:@""];


    // Loop through each line of text and apply the background color to just the text within that range.
    // This way, no whitespace / line breaks will be highlighted.
    __block int startRange = 0;
    [allLines enumerateObjectsUsingBlock:^(NSString *line, NSUInteger idx, BOOL *stop) {

        // The end range should be the length of the line, minus one for the whitespace.
        // If we are on the final line, there are no more line breaks so we use the whole line length.
        NSUInteger endRange = (idx+1 == allLines.count) ?  line.length : line.length-1;

        // Apply background color
        [someLongStringAttr addAttribute:NSBackgroundColorAttributeName
                                   value:[UIColor colorWithWhite:0 alpha:0.25]
                                   range:NSMakeRange(startRange, endRange)];

        // Update the start range to the next line
        startRange += line.length;
    }];



    // Set text of label
    someLabel.attributedText = someLongStringAttr;
}


#pragma mark - Utility Functions

static NSArray *getLinesForLabel(UILabel *label) {

    // Get the text from the label
    NSString *labelText = label.text;

    // Create an array to hold the lines of text
    NSMutableArray *allLines = [NSMutableArray array];

    while (YES) {

        // Get the length of the current line of text
        int length = getLengthOfTextInFrame(label, labelText) + 1;

        // Add this line of text to the array
        [allLines addObject:[labelText substringToIndex:length]];

        // Adjust the label text
        labelText = [labelText substringFromIndex:length];

        // Check for the final line
        if(labelText.length<length) {
            [allLines addObject:labelText];
            break;
        }
    }

    return [NSArray arrayWithArray:allLines];
}

static int getLengthOfTextInFrame(UILabel *label, NSString *text) {

    // Create a block for getting the bounds of the current peice of text.
    CGRect (^boundingRectForLength)(int) = ^CGRect(int length) {
        NSString *cutText = [text substringToIndex:length];
        CGRect textRect = [cutText boundingRectWithSize:CGSizeMake(label.frame.size.width, CGFLOAT_MAX)
                                                options:NSStringDrawingUsesLineFragmentOrigin
                                             attributes:@{NSFontAttributeName : label.font}
                                                context:nil];
        return textRect;
    };

    // Get the frame of the string for one character
    int length = 1;
    int lastSpace = 1;
    CGRect textRect = boundingRectForLength(length);
    CGFloat oneLineHeight = CGRectGetHeight(textRect);

    // Keep adding one character to the string until the height changes, then you know you have a new line
    while (textRect.size.height <= oneLineHeight)
    {
        // If the next character is white space, save the current length.
        // It could be the end of the line.
        // This will not work for character wrap.
        if ([[text substringWithRange:NSMakeRange (length, 1)] isEqualToString:@" "]) {
            lastSpace = length;
        }

        // Increment length and get the new bounds
        textRect = boundingRectForLength(++length);
    }

    return lastSpace;
}

这篇关于突出显示UILabel中的文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆