Sumeet Mourya
Sumeet Mourya

Reputation: 434

Dynamically getting height of UILabel according to Text return different Value for iOS 7.0 and iOS 6.1

I am using the this method for getting the height of the UILabel Dynamically:

+(CGSize) GetSizeOfLabelForGivenText:(UILabel*)label Font:(UIFont*)fontForLabel Size:  (CGSize)LabelSize{
    label.numberOfLines = 0;
    CGSize labelSize = [label.text sizeWithFont:fontForLabel constrainedToSize:LabelSize lineBreakMode:NSLineBreakByCharWrapping];
    return (labelSize);
}

With this solution I am getting the exact size of UILabel if my code is running on below iOS 8 but if I run my application on iOS7 then it is returns a different value.

Upvotes: 22

Views: 47396

Answers (13)

Preetam Jadakar
Preetam Jadakar

Reputation: 4561

You have to dynamically set the frame, like below:

Tested on iOS 6 to iOS 12.2

Swift:

let constrainedSize = CGSize(width: self.titleLable.frame.size.width, height:9999)

let attributesDictionary = [NSAttributedString.Key.font: UIFont.init(name: "HelveticaNeue", size: 11.0)]

let string = NSAttributedString.init(string: "textToShow", attributes: attributesDictionary as [NSAttributedString.Key : Any])

var requiredHeight = string.boundingRect(with: constrainedSize, options: .usesLineFragmentOrigin, context: nil)


if (requiredHeight.size.width > self.titleLable.frame.size.width) {
    requiredHeight = CGRect(x: 0, y: 0, width: self.titleLable.frame.size.width, height: requiredHeight.size.height)
}
var newFrame = self.titleLable.frame
newFrame.size.height = requiredHeight.size.height
self.titleLable.frame = newFrame

Objective C:

CGSize constrainedSize = CGSizeMake(self.resizableLable.frame.size.width  , 9999);

NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [UIFont fontWithName:@"HelveticaNeue" size:11.0], NSFontAttributeName,
                                      nil];

NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"textToShow" attributes:attributesDictionary];

CGRect requiredHeight = [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];

if (requiredHeight.size.width > self.resizableLable.frame.size.width) {
    requiredHeight = CGRectMake(0,0, self.resizableLable.frame.size.width, requiredHeight.size.height);
}
CGRect newFrame = self.resizableLable.frame;
newFrame.size.height = requiredHeight.size.height;
self.resizableLable.frame = newFrame;

Upvotes: 25

Ladd.c
Ladd.c

Reputation: 1013

This method is used and tested by me from iOS 7 to iOS 11.4

+ (CGFloat)getLabelHeight:(UILabel*)label
{
    NSParameterAssert(label);
    CGSize limitLabel = CGSizeMake(label.frame.size.width, CGFLOAT_MAX);
    CGSize size;

    NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
    CGSize labelBox = [label.text boundingRectWithSize: limitLabel
                                                  options: NSStringDrawingUsesLineFragmentOrigin
                                               attributes: @{ NSFontAttributeName:label.font }
                                                  context: context].size;

    size = CGSizeMake(ceil(labelBox.width), ceil(labelBox.height));
    return size.height;
}

So you can use like this:

CGFloat sizeOfFontTest = 12.0;
    UILabel *testLabel = [[UILabel alloc] initWithFrame: CGRectMake(0, 0, 100, 0)];
    [testLabel setFont: [UIFont systemFontOfSize: sizeOfFontTest]];
    [testLabel setText: @"Hello Stackoverflow Large String Example"];

    CGFloat heightTestLabel = [self getLabelHeight: testLabel];

    [testLabel setFrame: CGRectMake(testLabel.frame.origin.x, testLabel.frame.origin.y, testLabel.frame.size.width, heightAddrsLab)];
    [testLabel setNumberOfLines: sizeOfFontTest / heightTestLabel];

Upvotes: 0

Zulqarnain Mustafa
Zulqarnain Mustafa

Reputation: 1653

I have a situation where i need to set the height of label dynamically according to text. I am using Xcode 7.1 and my project deployment target is 7.0 but i tested it on iOS 9 simulator and following solution works for me. Here is the solution: First of of you will create a dictionary like this:

NSDictionary *attributes = @{NSFontAttributeName:self.YOUR_LABEL.font};

now we will calculate the height and width for our text and pass the newly created dictionary.

    CGRect rect = [YOUR_TEXT_STRING boundingRectWithSize:CGSizeMake(LABEL_WIDTH, CGFLOAT_MAX)
                                          options:NSStringDrawingUsesLineFragmentOrigin
                                       attributes:attributes
                                          context:nil];

Then we will set the frame of our LABEL:

    self.YOUR_LABEL.frame = CGRectMake(self.YOUR_LABEL.frame.origin.x, self.YOUR_LABEL.frame.origin.y, self.YOUR_LABEL.frame.size.width, rect.size.height);

THIS IS HOW I SUCCESSFULLY SET THE FRAME OF MY LABEL ACCORDING TO TEXT.

Upvotes: 0

Groot
Groot

Reputation: 14251

The method sizeWithFont:constrainedToSize:lineBreakMode: is deprecated in iOS7. You should use sizeWithAttributes: instead.

Example:

NSDictionary *fontAttributes = @{NSFontAttributeName : [UIFont systemFontOfSize:15]};
CGSize textSize = [self.myLabel.text sizeWithAttributes:fontAttributes];
CGFloat textWidth = textSize.width;
CGFloat textHeight = textSize.height;

Upvotes: 0

AlexKoren
AlexKoren

Reputation: 1605

Super simple. Just get the area of the text, divide by width, then round up to the nearest height that will fit your font.

+ (CGFloat)heightForText:(NSString*)text font:(UIFont*)font withinWidth:(CGFloat)width {
    CGSize size = [text sizeWithAttributes:@{NSFontAttributeName:font}];
    CGFloat area = size.height * size.width;
    CGFloat height = roundf(area / width);
    return ceilf(height / font.lineHeight) * font.lineHeight;
}

Very much a plug and play solution. I use it in a helper class a lot, especially for dynamically sized UITableViewCells.

Hope this helps others in the future!

Upvotes: 0

Js Lim
Js Lim

Reputation: 3705

I all the time use sizeThatFits:

CGRect frame = myLabel.frame;
CGSize constraint = CGSizeMake(CGRectGetWidth(myLabel.frame), 20000.0f);
CGSize size = [myLabel sizeThatFits:constraint];
frame.size.height = size.height;
myLabel.frame = frame;

You can try this

Upvotes: 0

user3762921
user3762921

Reputation: 1

this code is for moving four labels clockwise with the button tap, by using function for button:

(void)onclick
{
    CGRect newFrame;
    CGRect newFrame1 = lbl1.frame;
    CGRect newFrame2 = lbl2.frame;
    CGRect newFrame3 = lbl3.frame;
    CGRect newFrame4 = lbl4.frame;
    lbl1.frame=newFrame;
    lbl4.frame=newFrame1;
    lbl3.frame=newFrame4;
    lbl2.frame=newFrame3;
    lbl1.frame=newFrame2;
}

Upvotes: -6

Charitha Basnayake
Charitha Basnayake

Reputation: 303

This is what I came up finally and hope this will help you. I checked iOS version as Apple itself doing in the iOS 7 UI Transition Guide, which involves checking the Foundation Framework version and used #pragma to suppress the Deprecated: warning raising by iOS 7 or later with "- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size".

+ (CGSize)getStringBoundingSize:(NSString*)string forWidth:(CGFloat)width withFont:(UIFont*)font{

    CGSize maxSize = CGSizeMake(width, CGFLOAT_MAX);
    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
        // for iOS 6.1 or earlier
        // temporarily suppress the warning and then turn it back on
        // since sizeWithFont:constrainedToSize: deprecated on iOS 7 or later
        #pragma clang diagnostic push
        #pragma clang diagnostic ignored "-Wdeprecated-declarations"
            maxSize = [string sizeWithFont:font constrainedToSize:maxSize];
        #pragma clang diagnostic pop

    } else {
        // for iOS 7 or later
        maxSize = [string sizeWithAttributes:@{NSFontAttributeName:font}];

    }
    return maxSize;
}

Upvotes: 0

Armin
Armin

Reputation: 1150

The accepted answer is too long. You can use the following:

+(CGSize) GetSizeOfLabelForGivenText:(UILabel*)label Font:(UIFont*)fontForLabel Size:  (CGSize) constraintSize{
    label.numberOfLines = 0;
    CGRect labelRect = [label.text boundingRectWithSize:constraintSize options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:@{NSFontAttributeName:fontForLabel} context:nil];
    return (labelRect.size);
}

Upvotes: 1

stackOverFlew
stackOverFlew

Reputation: 1499

Accepted answer didn't satisfy me so I had to dig this up in my code:

CGSize possibleSize = [string sizeWithFont:[UIFont fontWithName:@"HelveticaNeue" size:10] //font you are using
                          constrainedToSize:CGSizeMake(skillsMessage.frame.size.width,9999)
                              lineBreakMode:NSLineBreakByWordWrapping];


CGRect newFrame = label.frame;
newFrame.size.height = possibleSize.height;
label.frame = newFrame;

Upvotes: 2

Andrew Bennett
Andrew Bennett

Reputation: 930

Here's a total solution for width and height. Put these in your AppDelegate:

+(void)fixHeightOfThisLabel:(UILabel *)aLabel
{
    aLabel.frame = CGRectMake(aLabel.frame.origin.x,
                              aLabel.frame.origin.y,
                              aLabel.frame.size.width,
                              [AppDelegate heightOfTextForString:aLabel.text
                                                         andFont:aLabel.font
                                                         maxSize:CGSizeMake(aLabel.frame.size.width, MAXFLOAT)]);
}

+(CGFloat)heightOfTextForString:(NSString *)aString andFont:(UIFont *)aFont maxSize:(CGSize)aSize
{
    // iOS7
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
    {
        CGSize sizeOfText = [aString boundingRectWithSize: aSize
                                                  options: (NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                               attributes: [NSDictionary dictionaryWithObject:aFont
                                                                                       forKey:NSFontAttributeName]
                                                  context: nil].size;

        return ceilf(sizeOfText.height);
    }

    // iOS6
    CGSize textSize = [aString sizeWithFont:aFont
                          constrainedToSize:aSize
                              lineBreakMode:NSLineBreakByWordWrapping];
    return ceilf(textSize.height;
}

+(void)fixWidthOfThisLabel:(UILabel *)aLabel
{
    aLabel.frame = CGRectMake(aLabel.frame.origin.x,
                              aLabel.frame.origin.y,
                                [AppDelegate widthOfTextForString:aLabel.text
                                                          andFont:aLabel.font
                                                          maxSize:CGSizeMake(MAXFLOAT, aLabel.frame.size.height)],
                              aLabel.frame.size.height);
}

+(CGFloat)widthOfTextForString:(NSString *)aString andFont:(UIFont *)aFont maxSize:(CGSize)aSize
{
    // iOS7
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
    {
        CGSize sizeOfText = [aString boundingRectWithSize: aSize
                                                  options: (NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                               attributes: [NSDictionary dictionaryWithObject:aFont
                                                                                       forKey:NSFontAttributeName]
                                                  context: nil].size;

        return ceilf(sizeOfText.width);
    }

    // iOS6
    CGSize textSize = [aString sizeWithFont:aFont
                          constrainedToSize:aSize
                              lineBreakMode:NSLineBreakByWordWrapping];
    return ceilf(textSize.width);
}

then to use this, set the label's text:

label.numberOfLines = 0;
label.text = @"Everyone loves Stack OverFlow";

and call:

[AppDelegate fixHeightOfThisLabel:label];

Note: label's numberOfLines has to be set to 0. Hope that helps.

Upvotes: 5

Sumeet Mourya
Sumeet Mourya

Reputation: 434

Whatever height I am getting via this code(method I have written in this question above).Its provide the height in float value (86.4) , once we get that and try to set that height to UILabel, but we need to get the value from the height with ceil (87) instead of the value as it is (86.4). I have resolved my problem with this approach. And thanks for your answers.

Upvotes: 0

Liam
Liam

Reputation: 12668

if you are using any of the system fonts, they changed in iOS 7 so they would be different sizes.


Also, sizeWithFont:constrainedToSize:lineBreakMode: is deprecated in iOS 7. Use sizeWithAttributes: instead (if you are on iOS 7)

Upvotes: 4

Related Questions