21
votes

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);
4
yes, thank you for pointing me the right direction. I did not find it myself before posting my question.Vilém Kurz

4 Answers

17
votes

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];
2
votes
CGSize  size = [label.text sizeWithFont:label.font minFontSize:10 actualFontSize:&actualFontSize forWidth:200 lineBreakMode:UILineBreakModeTailTruncation];
2
votes

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.

0
votes

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;