10

编辑:链接的“重复”问题仅涉及计算文本矩形。我需要在标签缩放后计算实际字体大小,而不是字符串大小。

现在不推荐使用此方法:

size = [self sizeWithFont:font // 20
              minFontSize:minFontSize // 14
           actualFontSize:&actualFontSize // 16
                 forWidth:maxWidth
            lineBreakMode:self.lineBreakMode];

当 UILabel 缩小文本大小以适应时,如何计算现在在 iOS 7 中的 UILabel 的字体大小?

4

8 回答 8

11

我有同样的问题,我需要知道实际大小才能使我的 UIView 中的其他 UILabel 匹配。

我知道这不是一个完美的解决方案,但也许它对你有用。

adjustsFontSizeToFitWidth我的解决方案是:我“手动”计算大小而不是使用。

CGSize initialSize = [_label.text sizeWithAttributes:@{NSFontAttributeName:_label.font}];
while ( initialSize.width > _label.frame.size.width ) {
    [_label setFont:[_label.font fontWithSize:_label.font.pointSize - 1]];
    initialSize = [_label.text sizeWithAttributes:@{NSFontAttributeName:_label.font}];
}
CGFloat actualSize = _label.font.pointSize;
于 2013-11-08T10:56:35.083 回答
9

摘自 Julius Bahr 在此页面上的回答,此方法非常适合在自动调整后获取实际字体大小:

- (CGFloat)getActualFontSizeForLabel:(UILabel *)label
{
    NSStringDrawingContext *labelContext = [NSStringDrawingContext new];
    labelContext.minimumScaleFactor = label.minimumScaleFactor;

    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:label.text attributes:@{ NSFontAttributeName: label.font }];
    [attributedString boundingRectWithSize:label.frame.size
                                   options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                                   context:labelContext];

    CGFloat actualFontSize = label.font.pointSize * labelContext.actualScaleFactor;
    return actualFontSize;
}

我在我的应用程序中使用它来获取三个不同标签的字体大小,我需要保持这些标签的大小同步,同时仍然允许它们自动缩小本地化翻译,这些翻译可能比原来的英文对应物长很多。

我为每个标签调用一次该方法,然后如果它们的值不同,我将标签的字体大小设置为三个中的最小值。

于 2015-06-06T02:41:57.430 回答
8

在 iOS 6 和 iOS 7 的绘图添加上,使用minFontSize已弃用。如果你想使用它并找到实际使用的字体大小,你需要使用你在问题中提到的弃用方法。UILabelNSString

的替代品minFontSizeminimumScaleFactor。如果您想找到实际使用的比例因子,您需要创建一个NSStringDrawingContext并在消息中传递它boundingRectWithSize:options:attributes:context:,如下所示:

NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
context.minimumScaleFactor = 0.7;
[label.text boundingRectWithSize:CGSizeMake(maxWidth, HUGE_VAL)
    options:NSStringDrawingUsesLineFragmentOrigin
    attributes:@{
        NSFontAttributeName: font
    } context:context];
CGFloat actualFontSize = font.pointSize * context.actualScaleFactor;
于 2013-10-05T17:00:26.180 回答
5

扩展费兰的答案

扩展以填充宽度或高度,以先命中者为准

斯威夫特版本

func getFontSizeToFitFrameOfLabel(label: UILabel) -> CGFloat
{
    var initialSize : CGSize = label.text!.sizeWithAttributes([NSFontAttributeName : label.font])

    if initialSize.width > label.frame.size.width ||
       initialSize.height > label.frame.size.height
    {
        while initialSize.width > label.frame.size.width ||
              initialSize.height > label.frame.size.height
        {
            label.font = label.font.fontWithSize(label.font.pointSize - 1)
            initialSize = label.text!.sizeWithAttributes([NSFontAttributeName : label.font])
        }
    } else {
        while initialSize.width < label.frame.size.width &&
              initialSize.height < label.frame.size.height
        {
            label.font = label.font.fontWithSize(label.font.pointSize + 1)
            initialSize = label.text!.sizeWithAttributes([NSFontAttributeName : label.font])
        }
        // went 1 point too large so compensate here
        label.font = label.font.fontWithSize(label.font.pointSize - 1)
    }
    return label.font.pointSize;
}

然后做这样的事情来使用它(比如你的标签名为title1Label)

 title1Label.frame = CGRect(x: 0.0, y: 0.0, width: view.frame.size.width, height: view.frame.size.height)
 // sets font to some nonzero size to begin with, it will change up or down to fit the label's frame
 title1Label.font = UIFont(name: "Super Mario 256", size: 45.0)
 title1Label.font = title1Label.font.fontWithSize(getFontSizeToFitFrameOfLabel(title1Label))
 // resize height to be a little larger than the font height
 title1Label.frame.size.height = title1Label.font.pointSize*1.3

目标 C 版本:

- (CGFloat) maxFontSize:(UILabel *)label{
   CGSize initialSize = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}];

   if (initialSize.width > label.frame.size.width ||
       initialSize.height > label.frame.size.height)
   {
       while (initialSize.width > label.frame.size.width ||
              initialSize.height > label.frame.size.height)
       {
           [label setFont:[label.font fontWithSize:label.font.pointSize - 1]];
           initialSize = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}];
       }
   } else {
       while (initialSize.width < label.frame.size.width &&
              initialSize.height < label.frame.size.height)
       {
           [label setFont:[label.font fontWithSize:label.font.pointSize + 1]];
           initialSize = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}];
       }
       // went 1 point too large so compensate here
       [label setFont:[label.font fontWithSize:label.font.pointSize - 1]];
   }
   return label.font.pointSize;
}
于 2015-06-26T01:14:43.970 回答
4

我的具体任务是在启用 adjustsFontSizeToFitWidth 的情况下同等地调整 2 个标签上的字体大小。该解决方案适用于 iOS 6 和 7。

+ (void)sizeLabelFontToMinSizeFor:(UILabel *)label1 and:(UILabel *)label2 {

NSStringDrawingContext *labelContext = [NSStringDrawingContext new];
labelContext.minimumScaleFactor = label1.minimumScaleFactor;

NSAttributedString *attributedString1 = [[NSAttributedString alloc] initWithString:label1.text attributes:@{NSFontAttributeName : label1.font}];
// the NSStringDrawingUsesLineFragmentOrigin and NSStringDrawingUsesFontLeading options are magic
[attributedString1 boundingRectWithSize:label1.frame.size options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:labelContext];

CGFloat actualFontSize1 = label1.font.pointSize * labelContext.actualScaleFactor;

labelContext = [NSStringDrawingContext new];
labelContext.minimumScaleFactor = label2.minimumScaleFactor;

NSAttributedString *attributedString2 = [[NSAttributedString alloc] initWithString:label2.text attributes:@{NSFontAttributeName : label2.font}];
[attributedString2 boundingRectWithSize:label2.frame.size options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:labelContext];

CGFloat actualFontSize2 = label2.font.pointSize * labelContext.actualScaleFactor;

CGFloat minSize = MIN(actualFontSize1, actualFontSize2);

label1.font = [UIFont fontWithName:RCDefaultFontName size:minSize];
label2.font = [UIFont fontWithName:RCDefaultFontName size:minSize];
}
于 2014-02-25T15:13:51.367 回答
2

下一个代码不支持 minFontSize 和 lineBreakMode 所以如果你需要它们你应该自己改进它:

CGSize NSString_sizeWithFont(NSString * str, UIFont *font) {
    CGSize result;
    if (NO == [str respondsToSelector: @selector(sizeWithAttributes:)]) {
        // legacy way
        result = [str sizeWithFont: font];
    } else {
        // modern way
        NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:
                               font, NSFontAttributeName, nil];
        result = [str sizeWithAttributes: dict];
    }
    return result;
}

UIFont * NSString_calcActualFont(NSString * str, UIFont * initialFont,
                                 CGSize sizeLimit, CGSize * actualSize)
{
    const CGSize curSize = NSString_sizeWithFont(str, initialFont);

    CGFloat actualFontSize = initialFont.pointSize;
    actualFontSize *= MIN(sizeLimit.width / curSize.width, sizeLimit.height / curSize.height);

    UIFont * actualFont = [initialFont fontWithSize: floorf(actualFontSize)];
    *actualSize = NSString_sizeWithFont(str, actualFont);

    return actualFont;
}
于 2014-10-20T07:24:48.590 回答
0

单行 UILabel 的简单解决方案:

//myLabel - initial label

UILabel *fullSizeLabel = [UILabel new];
fullSizeLabel.font = myLabel.font;
fullSizeLabel.text = myLabel.text;
[fullSizeLabel sizeToFit];

CGFloat actualFontSize = myLabel.font.pointSize * (myLabel.bounds.size.width / fullSizeLabel.bounds.size.width);

//correct, if new font size bigger than initial
actualFontSize = actualFontSize < myLabel.font.pointSize ? actualFontSize : myLabel.font.pointSize;
于 2016-11-12T01:14:21.410 回答
-1

Erik van der Neut 的代码对我有用,所以我用 Swift 翻译了它,并将它包装在一个 UILabel 扩展中:

extension UILabel {

    public func actualFontSize()-> CGFloat {
        let context = NSStringDrawingContext()
        context.minimumScaleFactor = self.minimumScaleFactor

        let attributedString = NSAttributedString(string: self.text ?? "", attributes: [NSFontAttributeName: self.font])
        attributedString.boundingRectWithSize(self.frame.size, options: [.UsesLineFragmentOrigin], context: context)

        return (self.font.pointSize * context.actualScaleFactor)
    }
}
于 2016-01-28T18:59:49.060 回答