Подтвердить что ты не робот

Масштабирование размера шрифта по вертикали в UILabel

Я хочу взять стандартную UILabel и увеличить размер шрифта, чтобы он заполнил вертикальное пространство. Воспользовавшись принятым ответом на этот question, я определил подкласс в UILabel с этой реализацией drawRect:

- (void)drawRect:(CGRect)rect
{
    // Size required to render string
    CGSize size = [self.text sizeWithFont:self.font];

    // For current font point size, calculate points per pixel
    float pointsPerPixel = size.height / self.font.pointSize;

    // Scale up point size for the height of the label
    float desiredPointSize = rect.size.height * pointsPerPixel;

    // Create and assign new UIFont with desired point Size
    UIFont *newFont = [UIFont fontWithName:self.font.fontName size:desiredPointSize];
    self.font = newFont;

    // Call super
    [super drawRect:rect];
}

Но это не работает, поскольку он масштабирует шрифт за пределами нижней метки. Если вы хотите воспроизвести это, я начал с метки 289x122 (w x h), Helvetica в качестве шрифта и начальной точки. Размер 60, который удобно помещается на этикетке. Вот пример вывода из стандартного UILabel и моего подкласса с использованием строки "{Hg":

uilabel

uilabel subclass

Я посмотрел на шрифты descenders и ascenders, попробовал масштабирование, принимая их во внимание в разных комбинациях, но до сих пор не повезло. Любые идеи, это что-то общее с разными шрифтами, имеющими различную длину спуска и восхождения?

4b9b3361

Ответ 1

Ваш расчет для pointsPerPixel неверный путь вверх, он должен быть...

float pointsPerPixel =  self.font.pointSize / size.height;

Кроме того, возможно, этот код должен быть в layoutSubviews, поскольку единственный раз, когда шрифт должен быть изменен, это когда размер кадра изменяется.

Ответ 2

Интересно, имеет ли округление ошибку, приближающуюся к следующему большему размеру шрифта. Не могли бы вы просто масштабировать rec.size.height немного? Что-то вроде:

float desiredPointSize = rect.size.height *.90 * pointsPerPixel;

Обновление: Ваш расчет pointPerPixel обратный. Вы фактически делят пиксели точками шрифта, а не точками на пиксели. Меняйте их, и он работает каждый раз. Просто для тщательности, здесь образец кода, который я тестировал:

//text to render    
NSString *soString = [NSString stringWithFormat:@"{Hg"];
UIFont *soFont = [UIFont fontWithName:@"Helvetica" size:12];

//box to render in
CGRect rect = soLabel.frame;

//calculate number of pixels used vertically for a given point size. 
//We assume that pixel-to-point ratio remains constant.
CGSize size = [soString sizeWithFont:soFont];
float pointsPerPixel;
pointsPerPixel = soFont.pointSize / size.height;   //this calc works
//pointsPerPixel = size.height / soFont.pointSize; //this calc does not work

//now calc which fontsize fits in the label
float desiredPointSize = rect.size.height * pointsPerPixel;
UIFont *newFont = [UIFont fontWithName:@"Helvetica" size:desiredPointSize];

//and update the display
[soLabel setFont:newFont];
soLabel.text = soString;

Это масштабируется и помещается внутри ящика для каждого размера, который я тестировал, от 40 до 60 пикселей шрифтов. Когда я отменил вычисление, я увидел те же результаты, когда шрифт был слишком высоким для поля.