如何根据标签可用的高度调整 UILabel 字体大小

Posted

技术标签:

【中文标题】如何根据标签可用的高度调整 UILabel 字体大小【英文标题】:How to adjust a UILabel font size based on the height available to the label 【发布时间】:2015-08-02 02:28:58 【问题描述】:

我正在使用 UILables 的自动布局和文本大小调整,它在宽度上工作得很好,但在高度上却没有那么多。

如果宽度上的文本有空间但高度上没有空间,则文本不会压缩

任何想法如何创建约束来做到这一点?或者这是不可能的,我怎样才能找到适合矩形的最小文本大小?

【问题讨论】:

【参考方案1】:

您可以将字体设置为自动填充标签的大小,并且可以选择不低于最小字体大小。只需将adjustsFontSizeToFitWidth 设置为YES。如果您需要更多信息,请查看UILabel Class Reference。

虽然布尔值称为“adjustsFontSizeToWidth”,但它实际上表示标签高度的最大尺寸,它将保留在标签的一行(或您指定的多行)上。

子类化 UILabel 并覆盖 layoutSubviews。然后每次 UILabel 改变其大小时,都会重新计算字体大小:

import Foundation
import UIKit

class LabelWithAdaptiveTextHeight: UILabel 

override func layoutSubviews() 
    super.layoutSubviews()
    font = fontToFitHeight()


// Returns an UIFont that fits the new label's height.
private func fontToFitHeight() -> UIFont 

    var minFontSize: CGFloat = DISPLAY_FONT_MINIMUM // CGFloat 18
    var maxFontSize: CGFloat = DISPLAY_FONT_BIG     // CGFloat 67
    var fontSizeAverage: CGFloat = 0
    var textAndLabelHeightDiff: CGFloat = 0

    while (minFontSize <= maxFontSize) 
        fontSizeAverage = minFontSize + (maxFontSize - minFontSize) / 2

        if let labelText: NSString = text 
            let labelHeight = frame.size.height

            let testStringHeight = labelText.sizeWithAttributes(
                [NSFontAttributeName: font.fontWithSize(fontSizeAverage)]
            ).height

            textAndLabelHeightDiff = labelHeight - testStringHeight

            if (fontSizeAverage == minFontSize || fontSizeAverage == maxFontSize) 
                if (textAndLabelHeightDiff < 0) 
                    return font.fontWithSize(fontSizeAverage - 1)
                
                return font.fontWithSize(fontSizeAverage)
            

            if (textAndLabelHeightDiff < 0) 
                maxFontSize = fontSizeAverage - 1

             else if (textAndLabelHeightDiff > 0) 
                minFontSize = fontSizeAverage + 1

             else 
                return font.fontWithSize(fontSizeAverage)
            
        
    
    return font.fontWithSize(fontSizeAverage)


【讨论】:

我一直在尝试 adjustsFontSizeToFitWidth 不工作正在剪切文本的顶部 我现在不在 Mac 上,我必须等到今晚才能测试它! :/ 但我会告诉你的。【参考方案2】:

Swift 3.0 适合任何新来这里的人。

非常感谢@tymac 的原始答案。

真正帮助我在使我的应用程序通用时不必担心文本大小。

import UIKit
import Foundation

class LabelWithAdaptiveTextHeight: UILabel 

    override func layoutSubviews() 
        super.layoutSubviews()
        font = fontToFitHeight()
    

    // Returns an UIFont that fits the new label's height.
    private func fontToFitHeight() -> UIFont 

        var minFontSize: CGFloat = 20
        var maxFontSize: CGFloat = 250
        var fontSizeAverage: CGFloat = 0
        var textAndLabelHeightDiff: CGFloat = 0

        while (minFontSize <= maxFontSize) 
            fontSizeAverage = minFontSize + (maxFontSize - minFontSize) / 2

            if let labelText: String = text 
                let labelHeight = frame.size.height

                let testStringHeight = labelText.size(attributes: [NSFontAttributeName: font.withSize(fontSizeAverage)]).height

                textAndLabelHeightDiff = labelHeight - testStringHeight

                if (fontSizeAverage == minFontSize || fontSizeAverage == maxFontSize) 
                    if (textAndLabelHeightDiff < 0) 
                        return font.withSize(fontSizeAverage - 1)
                    
                    return font.withSize(fontSizeAverage)
                

                if (textAndLabelHeightDiff < 0) 
                    maxFontSize = fontSizeAverage - 1

                 else if (textAndLabelHeightDiff > 0) 
                    minFontSize = fontSizeAverage + 1

                 else 
                    return font.withSize(fontSizeAverage)
                
            
        
        return font.withSize(fontSizeAverage)
    

【讨论】:

令人惊讶的是,这不是像“adjustFontSizeToFitHeight”这样的标准功能 太棒了!对 Swift 5 稍作调整:let testStringHeight = labelText.size(withAttributes: [NSAttributedString.Key.font: font.withSize(fontSizeAverage)]).height ...如果您想将最大字体大小保持在您在界面生成器中设置的字体大小,您可以将 maxFontSize 调整为var maxFontSize: CGFloat = font.pointSize【参考方案3】:

对于任何感兴趣的人,这里是 tymac 的答案的 Objective-C 实现。

(我有点着急,没有时间修复小写 Gs、Js、Ps 和 Qs 被剪切,所以我迅速从计算函数中的平均文本大小中减去了两个,对不起。)

#import "LabelWithAdaptiveTextHeight.h"

#define DISPLAY_FONT_MINIMUM 6
#define DISPLAY_FONT_MAXIMUM 50

@interface LabelWithAdaptiveTextHeight ()

@end

@implementation LabelWithAdaptiveTextHeight

- (UIFont*)fontToFitHeight 
    float minimumFontSize = DISPLAY_FONT_MINIMUM;
    float maximumFontSize = DISPLAY_FONT_MAXIMUM;
    float fontSizeAverage = 0;
    float textAndLabelHeightDifference = 0;

    while(minimumFontSize <= maximumFontSize)
        fontSizeAverage = minimumFontSize + (maximumFontSize - minimumFontSize) / 2;
        if(self.text)
            float labelHeight = self.frame.size.height;
            float testStringHeight = [self.text sizeWithAttributes:@
                                                                NSFontAttributeName: [self.font fontWithSize:fontSizeAverage]
                                                                ].height;

            textAndLabelHeightDifference = labelHeight - testStringHeight;

            if(fontSizeAverage == minimumFontSize || fontSizeAverage == maximumFontSize)
                return [self.font fontWithSize:fontSizeAverage- (textAndLabelHeightDifference < 0)];
            
            if(textAndLabelHeightDifference < 0)
                maximumFontSize = fontSizeAverage - 1;
            
            else if(textAndLabelHeightDifference > 0)
                minimumFontSize = fontSizeAverage + 1;
            
            else
                return [self.font fontWithSize:fontSizeAverage];
            
        
        else 
            break; //Prevent infinite loop
        
    
    return [self.font fontWithSize:fontSizeAverage-2];


- (void)layoutSubviews 
    [super layoutSubviews];
    self.font = [self fontToFitHeight];


@end

【讨论】:

以上是关于如何根据标签可用的高度调整 UILabel 字体大小的主要内容,如果未能解决你的问题,请参考以下文章

如何调整字体大小以适应 UILabel 的高度和宽度

多行 UILabel 没有正确换行 [重复]

以编程方式动态调整多行 UILabel 和随附的表格视图单元格

根据实际可见字母高度在 UILabel 中垂直居中文本

UILabel 动画调整大小副作用

根据字体多少使UILabel自动调节尺寸