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,以便它可以与多行工作。
- 将“自动缩放”设置为“最小字体大小”。
- 设置字体到最大的理想字体大小(我select了20)
- 将“换行”从“换行”改为“截尾”。
来源: 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 } } } }