dynamic改变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会得到一堆不同的值。 一些用多个句子,其他用五或六个单词。

如何设置UILabel ,使字体大小发生变化,使文本始终符合我定义的范围?

单线:

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

上面的代码会将文本的字体大小调整为(例如) 8 ,以便将文本放在标签中。 numberOfLines = 1是强制性的。

多行:

对于numberOfLines > 1有一种方法可以通过NSString的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; 

IOS 7

多行:

从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的回答,您可能想要创build一个类别,以便在您的其他应用程序中灵活使用。

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年。我不得不去找一个博客文章,将解释如何使用Swift的最新版本的iOS和XCode,以便它可以与多行工作。

  1. 将“自动缩放”设置为“最小字体大小”。
  2. 设置字体到最大的理想字体大小(我select了20)
  3. 将“换行”从“换行”改为“截尾”。

来源: http : //beckyhansmeyer.com/2015/04/09/autoshrinking-text-in-a-multiline-uilabel/

Swift版本:

 textLabel.adjustsFontSizeToFitWidth = true textLabel.minimumScaleFactor = 0.5 

这是一个UILabel的Swift扩展。 它运行二进制searchalgorithm,根据标签边界的宽度和高度调整字体大小。 经testing与iOS 9和自动布局一起工作。

用法:其中<label>是您需要调整字体大小的预定义的UILabel

 <label>.fitFontForSize() 

默认情况下,这个函数在5pt和300pt的字体大小的范围内进行search,并设置字体以使其文本“完全”在边界内(精确到1.0pt)。 您可以定义这些参数,例如,按照以下方式在0.1pts内精确地在1pt标签的当前字体大小之间进行search:

 <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()调用都可以自行删除

单行 – 有两种方法,你可以简单地改变。

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 120×120,最大字体大小为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]; 

该解决scheme适用于多线:

以下几篇文章,并要求一个function,可以自动缩放文本和调整行数以适应给定的标签大小,我自己写了一个函数。 (即一个短的string很好地适合一行,并使用大量的标签框架,而一个长的强行会自动分裂成2或3行,并相应地resize)

随意重新使用它,并根据需要调整。 确保在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; } 

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) } 

以下是实现animation字体大小更改的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]; } 

简单的扩展,只需调整最大和最小。

 extension UILabel { func adjustFontSizeToHeight() { // Initial size is max and the condition the min. for var size = 25 ; size >= 4 ; size-- { let font = UIFont(name: self.font!.fontName, size: CGFloat(size))! let attrString = NSAttributedString(string: self.text!, attributes: [NSFontAttributeName : font]) let rectSize = attrString.boundingRectWithSize(CGSizeMake(self.bounds.width, CGFloat.max), options: .UsesLineFragmentOrigin, context: nil) if rectSize.size.height <= self.bounds.height { self.font = font break } } } }