Как замаскировать UILabel в iOS — Objective-C

Я хочу создать подкласс UIView и поместить четыре UILabels друг над другом; верхняя метка будет MASK, 2-я метка будет обычной меткой с текстом, 3-я метка будет меткой со сплошным фоном без текста. нижняя метка будет такой же, как верхняя 2-я метка с другим цветным шрифтом. когда я отправил ширину третьей метки, она закроет нижнюю метку, показывающую частичный вид текста. Я хочу, чтобы второй текст был одного цвета, а непокрытая нижняя метка отображала шрифт другого цвета.

Возможно ли это? Если кто-то может объяснить, как маскировать в Objective-C, это тоже поможет.

Я пытаюсь создать UIView, который действует как индикатор выполнения, так как полоса заполняется до 60%, я хочу, чтобы верхний текст отображался белым цветом шрифта, когда нижний текст отображается другим цветом.


person Arcadian    schedule 15.02.2011    source источник
comment
У меня это работает, используя UILineBreakModeClip и накладывая метки друг на друга. Но клип, кажется, опускает последнюю букву; Я думал, что он должен обрезаться там, где заканчивается прямоугольник. Я хочу отобразить половину буквы W   -  person Arcadian    schedule 16.02.2011


Ответы (2)


Вы можете сделать это с помощью двух UILabels, одного внизу и одного, встроенного в другое представление сверху.

UILabel *bottomLabel = ...;
[self.view addSubview:bottomLabel];

UIView *topContainer = [[UIView alloc] initWithFrame:bottomLabel.frame];
topContainer.clipsToBounds = YES;
topContainer.opaque = NO;
topContainer.backgroundColor = [UIColor clearColor];

UILabel *topLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, bottomLabel.frame.size.width, bottomLabel.frame.size.height)];
topLabel.text = bottomLabel.text;
topLabel.opaque = NO;
topLabel.backgroundColor = [UIColor clearColor];

[topContainer addSubview:topLabel];
[self.view addSubview:topContainer];

Затем, когда вы хотите изменить прогресс, вы должны установить ширину topContainer. Это должно обрезать topLabel.

person Daniel Dickison    schedule 16.02.2011
comment
Позволит ли это частичный рендеринг персонажей? Цель состоит в том, чтобы убедиться, что если индикатор выполнения находится между символами, то этот персонаж должен отображаться двумя цветами. - person Arcadian; 16.02.2011
comment
Да. Это должно работать, потому что вы будете изменять размер родительского UIView вместо UILabel. - person Daniel Dickison; 16.02.2011
comment
Работает так, как я хочу. Спасибо. - person Arcadian; 17.02.2011

Вместо того, чтобы использовать четыре UILabel, почему бы не создать подкласс UILabel и не нарисовать его самостоятельно в методе drawRect:? Это будет выглядеть примерно так:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Set the mask
    CGContextClipToMask(context, self.bounds, /* mask image */);

    // Draw the text in a different font
    [self.text drawInRect:rect withFont:/* alternate font */];

    // Draw a solid background
    CGContextSetRGBFillColor(context, ...);
    CGContextFillRect(context, rect);

    // Draw the text normally
    [super drawRect:rect];
}

Для удобства вы можете сделать маскирующее изображение и альтернативные свойства шрифта вашего подкласса.

person Tony    schedule 16.02.2011
comment
Позволит ли это частичный рендеринг персонажей? Цель состоит в том, чтобы убедиться, что если индикатор выполнения находится между символами, то этот символ должен отображаться двумя цветами. - person Arcadian; 16.02.2011
comment
Вероятно, вы захотите использовать self.bounds в CGContextClipToMask, а не self.frame. - person titaniumdecoy; 30.03.2011
comment
@titaniumdecoy Спасибо, что заметили это, исправлено. - person Tony; 06.04.2011