Dynamically getting height of UILabel according to

2019-01-08 14:32发布

问题:

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.

回答1:

You have to dynamically set the frame, like below:

//Compatible for both ios6 and ios7.  

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;


回答2:

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.



回答3:

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)



回答4:

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;


回答5:

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);
}


回答6:

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



回答7:

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.



回答8:

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;
}


回答9:

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!



回答10:

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;


回答11:

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.



回答12:

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];


回答13:

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;
}