Динамически изменяемый размер шрифта UILabel - PullRequest
178 голосов
/ 01 февраля 2011

У меня в настоящее время есть UILabel:

factLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, 280, 100)];
factLabel.text = @"some text some text some text some text";
factLabel.backgroundColor = [UIColor clearColor];
factLabel.lineBreakMode = UILineBreakModeWordWrap;
factLabel.numberOfLines = 10;
[self.view addSubview:factLabel];

На протяжении всей жизни моего приложения для iOS factLabel получает кучу разных значений.Некоторые с несколькими предложениями, другие только с 5 или 6 словами.

Как настроить UILabel так, чтобы размер шрифта изменялся так, чтобы текст всегда соответствовал границам, которые я определил?

Ответы [ 12 ]

338 голосов
/ 01 февраля 2011

Одна строка:

factLabel.numberOfLines = 1;
factLabel.minimumFontSize = 8;
factLabel.adjustsFontSizeToFitWidth = YES;

Приведенный выше код отрегулирует размер шрифта вашего текста до (например) 8, пытаясь подогнать текст внутри метки.numberOfLines = 1 является обязательным.

Несколько строк:

Для numberOfLines > 1 существует метод определения размера конечного текста через sizeSSithringSSS:... UIKit добавление методов, например:

CGSize lLabelSize = [yourText sizeWithFont:factLabel.font
                                  forWidth:factLabel.frame.size.width
                             lineBreakMode:factLabel.lineBreakMode];

После этого вы можете просто изменить размер вашей этикетки, например, получив lLabelSize (при условии, что вы измените только высоту этикетки):

factLabel.frame = CGRectMake(factLabel.frame.origin.x, factLabel.frame.origin.y, factLabel.frame.size.width, lLabelSize.height);

iOS6

Одна строка:

Начиная с iOS6, minimumFontSize устарела.Строка

factLabel.minimumFontSize = 8.;

может быть изменена на:

factLabel.minimumScaleFactor = 8./factLabel.font.pointSize;

iOS7

Несколько строк:

Начиная с iOS7, sizeWithFont становится устаревшим.Многострочный регистр уменьшен до:

factLabel.numberOfLines = 0;
factLabel.lineBreakMode = NSLineBreakByWordWrapping;
CGSize maximumLabelSize = CGSizeMake(factLabel.frame.size.width, CGFLOAT_MAX);
CGSize expectSize = [factLabel sizeThatFits:maximumLabelSize];
factLabel.frame = CGRectMake(factLabel.frame.origin.x, factLabel.frame.origin.y, expectSize.width, expectSize.height);
66 голосов
/ 19 февраля 2013

minimumFontSize устарела в iOS 6. Вы можете использовать minimumScaleFactor.

yourLabel.adjustsFontSizeToFitWidth=YES;
yourLabel.minimumScaleFactor=0.5;

Это позаботится о размере шрифта в соответствии с шириной метки и текста.

24 голосов
/ 27 января 2014

На основе ответа @Eyal Ben Dov вы можете создать категорию, чтобы сделать ее гибкой для использования в других ваших приложениях.

Obs .: Я обновил его код, чтобы сделать его совместимым с iOS 7

- файл заголовка

#import <UIKit/UIKit.h>

@interface UILabel (DynamicFontSize)

-(void) adjustFontSizeToFillItsContents;

@end

- файл внедрения

#import "UILabel+DynamicFontSize.h"

@implementation UILabel (DynamicFontSize)

#define CATEGORY_DYNAMIC_FONT_SIZE_MAXIMUM_VALUE 35
#define CATEGORY_DYNAMIC_FONT_SIZE_MINIMUM_VALUE 3

-(void) adjustFontSizeToFillItsContents
{
    NSString* text = self.text;

    for (int i = CATEGORY_DYNAMIC_FONT_SIZE_MAXIMUM_VALUE; i>CATEGORY_DYNAMIC_FONT_SIZE_MINIMUM_VALUE; i--) {

        UIFont *font = [UIFont fontWithName:self.font.fontName size:(CGFloat)i];
        NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName: font}];

        CGRect rectSize = [attributedText boundingRectWithSize:CGSizeMake(self.frame.size.width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:nil];

        if (rectSize.size.height <= self.frame.size.height) {
            self.font = [UIFont fontWithName:self.font.fontName size:(CGFloat)i];
            break;
        }
    }

}

@end

- использование

#import "UILabel+DynamicFontSize.h"

[myUILabel adjustFontSizeToFillItsContents];

Приветствия

20 голосов
/ 14 июня 2015

Это 2015 год. Мне нужно было найти пост в блоге, где объяснялось бы, как это сделать для последней версии iOS и XCode со Swift, чтобы он работал с несколькими строками.

  1. установите для параметра «Автоусадка» значение «Минимальный размер шрифта».
  2. установить шрифт на максимально желаемый размер шрифта (я выбрал 20)
  3. Измените «Разрывы строк» ​​с «Перенос слов» на «Обрезать хвост».

Источник: http://beckyhansmeyer.com/2015/04/09/autoshrinking-text-in-a-multiline-uilabel/

19 голосов
/ 04 августа 2017

Одна строка - Есть два способа, которые вы можете просто изменить.

1- Прагматично (Swift 3)

Просто добавьте следующий код

    yourLabel.numberOfLines = 1;
    yourLabel.minimumScaleFactor = 0.7;
    yourLabel.adjustsFontSizeToFitWidth = true;

2 - Использование инспектора атрибутов UILabel

i- Select your label- Set number of lines 1.
ii- Autoshrink-  Select Minimum Font Scale from drop down
iii- Set Minimum Font Scale value as you wish , I have set 0.7 as in below image. (default is 0.5)

enter image description here

12 голосов
/ 03 июня 2015

Swift версия:

textLabel.adjustsFontSizeToFitWidth = true
textLabel.minimumScaleFactor = 0.5
7 голосов
/ 31 декабря 2015

Вот расширение Swift для UILabel. Он запускает алгоритм двоичного поиска, чтобы изменить размер шрифта на основе ширины и высоты границ метки. Протестировано для работы с iOS 9 и автопрокладкой.

ИСПОЛЬЗОВАНИЕ: Где <label> - это предопределенная UILabel, для которой требуется изменение размера шрифта

<label>.fitFontForSize()

По умолчанию эта функция выполняет поиск в диапазоне размеров шрифта 5pt и 300pt и устанавливает шрифт так, чтобы его текст «идеально» соответствовал границам (с точностью до 1.0pt). Вы можете определить параметры так, чтобы он, например, осуществлял поиск между 1pt и текущим размером шрифта метки точно в пределах 0.1pts следующим образом:

<label>.fitFontForSize(1.0, maxFontSize: <label>.font.pointSize, accuracy:0.1)

Скопируйте / вставьте следующий код в ваш файл

extension UILabel {

    func fitFontForSize(var minFontSize : CGFloat = 5.0, var maxFontSize : CGFloat = 300.0, accuracy : CGFloat = 1.0) {
        assert(maxFontSize > minFontSize)
        layoutIfNeeded() // Can be removed at your own discretion
        let constrainedSize = bounds.size
        while maxFontSize - minFontSize > accuracy {
            let midFontSize : CGFloat = ((minFontSize + maxFontSize) / 2)
            font = font.fontWithSize(midFontSize)
            sizeToFit()
            let checkSize : CGSize = bounds.size
            if  checkSize.height < constrainedSize.height && checkSize.width < constrainedSize.width {
                minFontSize = midFontSize
            } else {
                maxFontSize = midFontSize
            }
        }
        font = font.fontWithSize(minFontSize)
        sizeToFit()
        layoutIfNeeded() // Can be removed at your own discretion
    }

}

ПРИМЕЧАНИЕ: Каждый из вызовов layoutIfNeeded() можно удалить по своему усмотрению

4 голосов
/ 12 июня 2013

Это немного не сложно, но это должно работать, Например, предположим, что вы хотите ограничить вашу uilabel до 120x120, с максимальным размером шрифта 28:

magicLabel.numberOfLines = 0;
magicLabel.lineBreakMode = NSLineBreakByWordWrapping;
...
magicLabel.text = text;
    for (int i = 28; i>3; i--) {
        CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:(CGFloat)i] constrainedToSize:CGSizeMake(120.0f, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
        if (size.height < 120) {
            magicLabel.font = [UIFont systemFontOfSize:(CGFloat)i];
            break;
        }
    }
1 голос
/ 20 ноября 2012

Просто отправьте сообщение sizeToFit в UITextView. Он будет регулировать свою собственную высоту, чтобы просто соответствовать ее тексту. Он не изменит свою ширину или происхождение.

[textViewA1 sizeToFit];
0 голосов
/ 31 мая 2016

Вот код заполнения подкласса UILabel, который реализует изменение размера анимированного шрифта:

@interface SNTextLayer : CATextLayer

@end

@implementation SNTextLayer

- (void)drawInContext:(CGContextRef)ctx {
    // We override this to make text appear at the same vertical positon as in UILabel
    // (otherwise it's shifted tdown)
    CGFloat height = self.bounds.size.height;
    float fontSize = self.fontSize;
    // May need to adjust this somewhat if it's not aligned perfectly in your implementation
    float yDiff = (height-fontSize)/2 - fontSize/10;

    CGContextSaveGState(ctx);
    CGContextTranslateCTM(ctx, 0.0, yDiff);
    [super drawInContext:ctx];
     CGContextRestoreGState(ctx);
}

@end

@interface SNAnimatableLabel ()

@property CATextLayer* textLayer;

@end

@interface SNAnimatableLabel : UILabel

- (void)animateFontToSize:(CGFloat)fontSize withDuration:(double)duration;

@end



@implementation SNAnimatableLabel


- (void)awakeFromNib {
    [super awakeFromNib];
    _textLayer = [SNTextLayer new];
    _textLayer.backgroundColor = self.backgroundColor.CGColor;
    _textLayer.foregroundColor = self.textColor.CGColor;
    _textLayer.font = CGFontCreateWithFontName((CFStringRef)self.font.fontName);
    _textLayer.frame = self.bounds;
    _textLayer.string = self.text;
    _textLayer.fontSize = self.font.pointSize;
    _textLayer.contentsScale = [UIScreen mainScreen].scale;
    [_textLayer setPosition: CGPointMake(CGRectGetMidX(_textLayer.frame), CGRectGetMidY(_textLayer.frame))];
    [_textLayer setAnchorPoint: CGPointMake(0.5, 0.5)];
    [_textLayer setAlignmentMode: kCAAlignmentCenter];
    self.textColor = self.backgroundColor;
    // Blend text with background, so that it doens't interfere with textlayer text
    [self.layer addSublayer:_textLayer];
    self.layer.masksToBounds = NO;
}

- (void)setText:(NSString *)text {
    _textLayer.string = text;
    super.text = text;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    // Need to enlarge the frame, otherwise the text may get clipped for bigger font sizes
    _textLayer.frame = CGRectInset(self.bounds, -5, -5);
}

- (void)animateFontToSize:(CGFloat)fontSize withDuration:(double)duration {
    [CATransaction begin];
    [CATransaction setAnimationDuration:duration];
    _textLayer.fontSize = fontSize;
    [CATransaction commit];
}
...