如何使UILabel(UITextView)自动调整字体大小?

22

在自动调整字体大小 (属性 adjustsFontSizeToFitWidth 设置为 YES,文本字体大小被缩小以适应标签) 后,是否有可能获得最终字体大小?

我正在对 UILabel 中的 drawTextInRect 进行子类化,以将渐变放在文本上,但渐变的大小需要与字体大小相同。我无法获得已调整字体的正确大小...这是可能的吗?

  //draw gradient

    CGContextSaveGState(myContext);
        CGGradientRef glossGradient;
        CGColorSpaceRef rgbColorspace;
        size_t num_locations = 2;
        CGFloat locations[2] = { 0.0, 1.0 };
        CGFloat components[8] = { 1, 1, 1, 0.25,  // BOTTOM color
            1, 1, 1, 0.12 }; // UPPER color

    //scale and translate so that text would not be rotated 180 deg wrong
        CGContextTranslateCTM(myContext, 0, rect.size.height);
        CGContextScaleCTM(myContext, 1.0, -1.0);

//create mask
        CGImageRef alphaMask = CGBitmapContextCreateImage(myContext);
        CGContextClipToMask(myContext, rect, alphaMask);

        rgbColorspace = CGColorSpaceCreateDeviceRGB();
        glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);

    //gradient should be sized to actual font size. THIS IS THE PROBLEM - EVEN IF FONT IS AUTO ADUJSTED, I AM GETTING THE SAME ORIGINAL FONT SIZE!!!

        CGFloat fontCapHeightHalf = (self.font.capHeight/2)+5;
            CGRect currentBounds = rect;
        CGPoint topCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMidY(currentBounds)-fontCapHeightHalf);
        CGPoint midCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMidY(currentBounds)+fontCapHeightHalf);

        CGContextDrawLinearGradient(myContext, glossGradient, topCenter, midCenter, 0);

        CGGradientRelease(glossGradient);
        CGColorSpaceRelease(rgbColorspace);
    CGContextRestoreGState(myContext);

1
是的,谢谢您指引我正确的方向。在发布问题之前我没有找到它。 - Vilém Kurz
4个回答

17

您无法直接获取大小,但是可以轻松使用这些函数进行计算:

CGFloat actualFontSize;
[label.text sizeWithFont:label.font
             minFontSize:label.minimumFontSize
          actualFontSize:&actualFontSize
                forWidth:label.bounds.size.width
           lineBreakMode:label.lineBreakMode];

9
iOS 7中已被弃用,没有替代方法。 - openfrog
@openfrog 我在这里发布了一种替代方案,它可以在 iOS 7 上运行 - https://dev59.com/7mIj5IYBdhLWcg3wcEqI#20829315 它不是很简单,但它可以完成工作。 - Aaron Brager
@openfrog -sizeWithAttributes: 是一种替代方法。https://developer.apple.com/library/ios/documentation/uikit/reference/NSString_UIKit_Additions/Reference/Reference.html#//apple_ref/occ/instm/NSString/sizeWithAttributes: - Daniel Wood
@DanielWood 这个方法做另一件事情,Vilem 需要的是字体大小而不是盒子大小。 - Zeb

2
CGSize  size = [label.text sizeWithFont:label.font minFontSize:10 actualFontSize:&actualFontSize forWidth:200 lineBreakMode:UILineBreakModeTailTruncation];

1
这是否意味着使用Swift没有解决方案? - Narwhal

2
我的回答对原问题不是很有帮助,但每次搜索如何在自动调整后获取字体大小时,我都会在这里停止。 首先,我们都知道,在iOS 7.0中,sizeWithFont已被弃用,因此我们必须找到另一种解决方案。
我的解决方案适用于我的情况,在这种情况下,我有两个标签,一个标签具有更多的约束和更多的文本。
以下是一个逐步示例:
  • 具有相同宽度但文本长度不同的两个标签:

enter image description here

我想要在运行时调整主uilabel的字体大小,并使第二个标签具有相同的字体大小。

  • 减小两个标签的大小,使得第一个标签的文本适合框架,在这种情况下两个标签的大小都是12:

enter image description here

enter image description here

  • 在设置好位置约束之后(在我的示例中,标签保持在父视图的中心),更新两个标签的框架,以使它们完全适合文本:

enter image description here

  • 在两个标签之间的宽高比约束和主标签与父视图之间的宽度约束中添加 Aspect Ratio 约束:

enter image description here

enter image description here

  • 将第二个标签的宽度约束添加到主标签:

enter image description here

enter image description here

  • 现在您可以根据需要设置标签的字体大小:

enter image description here

以下是模拟器的屏幕截图:

enter image description here

由于宽度约束和最后一个图像中指定的字体参数,第一个标签根据屏幕大小调整大小,并相应地调整字体大小。 第二个标签的字体大小相同。

这只是一个示例,旨在展示我解决方案背后的“诀窍”:将标签的框架绑定到初始字体大小,以便在运行时保持相同。我想这种技术可以重新调整适用于大小可变的标签,只需在设置文本并调整框架以适应文本后,在标签之间添加约束即可。


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;

可以使用actualFontSize = min(actualFontSize, myLabel.font.pointSize)代替actualFontSize = actualFontSize < myLabel.font.pointSize ? actualFontSize : myLabel.font.pointSize; - Pavel Stepanov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接