How to get UILabel (UITextView) auto adjusted font size?
Asked Answered
R

4

22

Is it possible to get final font size, after autoadjusting? (property adjustsFontSizeToFitWidth set to YES, and text font size is being shrinked to fit into the label)

I am subclassing drawTextInRect in UILabel to put gradient on the text, but the gradient size needs to be the same, as the size of the font. I am not able to get proper size of the adjusted font...Is it even possible?

  //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);
Rosalie answered 8/9, 2010 at 16:25 Comment(2)
possible duplicate of How to calculate the size of a UIFont when text in label is constrained down to fit width?Heeheebiejeebies
yes, thank you for pointing me the right direction. I did not find it myself before posting my question.Howlond
P
17

You can't get the size directly, but you can calculate it easily enough using these functions:

CGFloat actualFontSize;
[label.text sizeWithFont:label.font
             minFontSize:label.minimumFontSize
          actualFontSize:&actualFontSize
                forWidth:label.bounds.size.width
           lineBreakMode:label.lineBreakMode];
Prinz answered 26/5, 2011 at 16:18 Comment(4)
Deprecated in iOS 7 with no alternative.Biancabiancha
@Biancabiancha I posted an alternative here which will work on iOS 7 - https://mcmap.net/q/153231/-autolayout-link-two-uilabels-to-have-the-same-font-size it's not as simple but it gets the job done.Decisive
@Biancabiancha -sizeWithAttributes: is the alternative. developer.apple.com/library/ios/documentation/uikit/reference/…:Maroc
@DanielWood This method do another thing, Vilem needs the font size and not the box size.Martyrology
H
2
CGSize  size = [label.text sizeWithFont:label.font minFontSize:10 actualFontSize:&actualFontSize forWidth:200 lineBreakMode:UILineBreakModeTailTruncation];
Hypodermic answered 26/5, 2011 at 10:40 Comment(1)
Does this mean there is no solution using Swift?Tesstessa
M
2

My answer isn't very helpful for the original question, but I end here every time I search how to get the font size after auto adjust. First of all, sizeWithFont has been deprecated in iOS 7.0, as we all know, so we have to find another solution.

My solution fits my case, in which I have two labels, one with more constraints and more text than second one.

Here is a step-by-step example:

  • two labels with same width and different text length:

enter image description here

I want, at run-time, the font size of the main uilabel to be resized and the second one to have the same font size.

  • decrease the size of both labels, so that the text of the first one fits the frame, in this case 12 for both:

enter image description here

enter image description here

  • after having set up the position constraints (in my example, the labels stay in the center of the parent view), update the both labels' frames so that they fit the text exactly:

enter image description here

  • add the Aspect Ratio constraints between width and height to both labels and the width constraint between the main label and the parent view:

enter image description here

enter image description here

  • add the width constraint from the second label to the main label:

enter image description here

enter image description here

  • now you can set font size of the labels as you wish:

enter image description here

Here is a screenshot of the Simulator:

enter image description here

The first label is resized according to the screen size and the font size is adjusted consequently. The font size of the second label is the same due to the width constraint and the font's parameters specified in the last image.

This is only an example that aims to showcase the "trick" behind my solution: bind the frames of the labels at an initial font size, so that it will be the same at run-time. I imagine that this technique could be re-adapted to labels with a variable size, just by adding the constraints between labels after having set the text and having resized the frame to fit the text.

Martyrology answered 7/7, 2015 at 15:10 Comment(0)
S
0

This simple solution works fine for one-line 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;
Slipcover answered 12/11, 2016 at 1:16 Comment(1)
Instead of actualFontSize = actualFontSize < myLabel.font.pointSize ? actualFontSize : myLabel.font.pointSize; it's also possible to use actualFontSize = min(actualFontSize, myLabel.font.pointSize)Devour

© 2022 - 2024 — McMap. All rights reserved.