首页 文章

动态更改UILabel的字体大小

提问于
浏览
171

我目前有一个 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 回答

  • 64

    单线:

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

    上面的代码会将文本的字体大小调整为(例如) 8 ,尝试在标签中插入文本 . numberOfLines = 1 是强制性的 .

    多行:

    对于 numberOfLines > 1 ,有一种方法可以通过NSString's UIKit addition方法计算出最终文本的大小,例如:

    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);
    
  • 0

    minimumFontSize 已被iOS 6弃用 . 您可以使用 minimumScaleFactor .

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

    这将根据标签和文本的宽度来处理您的字体大小 .

  • 1

    根据@Eyal Ben Dov的回答,您可能希望创建一个类别,以便在您的其他应用程序中灵活使用 .

    Obs . :我已经更新了他的代码以与iOS 7兼容

    -Header file

    #import <UIKit/UIKit.h>
    
    @interface UILabel (DynamicFontSize)
    
    -(void) adjustFontSizeToFillItsContents;
    
    @end
    

    -Implementation file

    #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
    

    -Usage

    #import "UILabel+DynamicFontSize.h"
    
    [myUILabel adjustFontSizeToFillItsContents];
    

    干杯

  • 4

    这是2015年 . 我不得不去寻找一篇博文,解释如何使用Swift为最新版本的iOS和XCode做到这一点,以便它可以使用多行 .

    • 将“自动收缩”设置为“最小字体大小” .

    • 将字体设置为最大的理想字体大小(我选择了20)

    • 将“换行符”从“自动换行”更改为“截断尾巴” .

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

  • 19

    Single line - 有两种方法,你可以简单地改变 .

    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

  • 11

    Swift版本:

    textLabel.adjustsFontSizeToFitWidth = true
    textLabel.minimumScaleFactor = 0.5
    
  • 0

    这是UILabel的Swift扩展 . 它运行二进制搜索算法,根据标签边界的宽度和高度调整字体大小 . 经测试可与iOS 9和autolayout配合使用 .

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

    <label>.fitFontForSize()
    

    默认情况下,此函数在5pt和300pt字体大小的范围内搜索,并将字体设置为在边界内适合其文本"perfectly"(准确度在1.0pt内) . 您可以定义参数,以便它以下列方式在 0.1pts 内准确地在 1ptlabel's current font size 之间进行搜索:

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

    Copy/Paste the following code into your file

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

    NOTE: 每个 layoutIfNeeded() 电话都可以自行决定删除

  • 331

    它有点不复杂,但这应该工作,例如,假设您想要将您的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;
            }
        }
    
  • 20

    只需将sizeToFit消息发送到UITextView即可 . 它将调整自己的高度以适应其文本 . 它不会改变自己的宽度或原点 .

    [textViewA1 sizeToFit];
    
  • 0

    Swift 2.0 Version:

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

    此解决方案适用于多行:

    在关注了几篇文章,并且需要一个能够自动缩放文本并将行数调整到最适合给定标签大小的函数之后,我自己编写了一个函数 . (即,一根短线很适合在一条线上并使用大量的标签框架,而一根长线会自动分割成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;
    }
    
  • 23

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

相关问题