Динамическое изменение размера шрифта UILabel
в настоящее время у меня 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 ответов:
одну строку:
factLabel.numberOfLines = 1; factLabel.minimumFontSize = 8; factLabel.adjustsFontSizeToFitWidth = YES;приведенный выше код будет регулировать размер шрифта вашего текста до (например)
8пытается вписать ваш текст в метку.numberOfLines = 1является обязательным.несколько строк:
на
numberOfLines > 1существует метод, чтобы выяснить размер окончательного текста через добавление UIKit NSString методы, например: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);
minimumFontSizeбыл устаревшим с iOS 6. Вы можете использоватьminimumScaleFactor.yourLabel.adjustsFontSizeToFitWidth=YES; yourLabel.minimumScaleFactor=0.5;Это позаботится о вашем размере шрифта в соответствии с шириной метки и текста.
на основе ответа @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];Ура
Это 2015 год. Мне нужно было найти сообщение в блоге, которое объяснило бы, как это сделать для последней версии iOS и XCode с Swift, чтобы он работал с несколькими строками.
- установите "Autoshrink" в " минимальный размер шрифта."
- установите шрифт на самый большой желаемый размер шрифта (я выбрал 20)
- изменить "разрывы строк" с "перенос слов" на " усечение Хвост."
источник: http://beckyhansmeyer.com/2015/04/09/autoshrinking-text-in-a-multiline-uilabel/
один строка- есть два способа, вы можете просто изменить.
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)
вот быстрое расширение для UILabel. Он запускает алгоритм двоичного поиска для изменения размера шрифта на основе ширины и высоты границ метки. Протестировано для работы с iOS 9 и autolayout.
использование: здесь
<label>Это ваша предопределенная UILabel, которая нуждается в изменении размера шрифта<label>.fitFontForSize()по умолчанию эта функция выполняет поиск в пределах 5pt и 300pt размеров шрифта и устанавливает шрифт, чтобы соответствовать его тексту "отлично" в пределах (с точностью до 1.0 pt). Вы можете определить параметры так, чтобы он, например, искал между 1pt и текущий размер шрифта метки точно в пределах 0.1 pts следующим образом:
<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()звонки могут быть удалены по своему усмотрению
его немного не сложно, но это должно работать, например, допустим, вы хотите закрыть свой 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; } }
просто отправьте сообщение sizeToFit в UITextView. Он будет регулировать свою собственную высоту, чтобы просто соответствовать его тексту. Он не будет изменять свою собственную ширину или происхождение.
[textViewA1 sizeToFit];
Версия Swift 2.0:
private func adapteSizeLabel(label: UILabel, sizeMax: CGFloat) { label.numberOfLines = 0 label.lineBreakMode = NSLineBreakMode.ByWordWrapping let maximumLabelSize = CGSizeMake(label.frame.size.width, sizeMax); let expectSize = label.sizeThatFits(maximumLabelSize) label.frame = CGRectMake(label.frame.origin.x, label.frame.origin.y, expectSize.width, expectSize.height) }
это решение работает для многострочных:
после следования нескольким статьям и требуя функции, которая автоматически масштабировала бы текст и регулировала количество строк, чтобы наилучшим образом соответствовать заданному размеру метки, я написал функцию сам. (т. короткая строка будет хорошо вписываться в одну строку и использовать большое количество рамки метки, тогда как длинная сильная автоматически разделится на 2 или 3 строки и соответственно отрегулирует размер)
Не стесняйтесь повторно использовать его и настроить как требуемый. Убедитесь, что вы называете его после
viewDidLayoutSubviewsзакончил так, что начальная рамка метки была установлена.+ (void)setFontForLabel:(UILabel *)label withMaximumFontSize:(float)maxFontSize andMaximumLines:(int)maxLines { int numLines = 1; float fontSize = maxFontSize; CGSize textSize; // The size of the text CGSize frameSize; // The size of the frame of the label CGSize unrestrictedFrameSize; // The size the text would be if it were not restricted by the label height CGRect originalLabelFrame = label.frame; frameSize = label.frame.size; textSize = [label.text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize: fontSize]}]; // Work out the number of lines that will need to fit the text in snug while (((textSize.width / numLines) / (textSize.height * numLines) > frameSize.width / frameSize.height) && (numLines < maxLines)) { numLines++; } label.numberOfLines = numLines; // Get the current text size label.font = [UIFont systemFontOfSize:fontSize]; textSize = [label.text boundingRectWithSize:CGSizeMake(frameSize.width, CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:@{NSFontAttributeName : label.font} context:nil].size; // Adjust the frame size so that it can fit text on more lines // so that we do not end up with truncated text label.frame = CGRectMake(label.frame.origin.x, label.frame.origin.y, label.frame.size.width, label.frame.size.width); // Get the size of the text as it would fit into the extended label size unrestrictedFrameSize = [label textRectForBounds:CGRectMake(0, 0, label.bounds.size.width, CGFLOAT_MAX) limitedToNumberOfLines:numLines].size; // Keep reducing the font size until it fits while (textSize.width > unrestrictedFrameSize.width || textSize.height > frameSize.height) { fontSize--; label.font = [UIFont systemFontOfSize:fontSize]; textSize = [label.text boundingRectWithSize:CGSizeMake(frameSize.width, CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:@{NSFontAttributeName : label.font} context:nil].size; unrestrictedFrameSize = [label textRectForBounds:CGRectMake(0, 0, label.bounds.size.width, CGFLOAT_MAX) limitedToNumberOfLines:numLines].size; } // Set the label frame size back to original label.frame = originalLabelFrame; }
вот код заполнения подкласса 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]; }

Comments