ios Dynamic sizing labels
Asked Answered
L

5

28

I've tried to search online, but haven't found a clear answer for my issue so I've come to ask for your expert advice. I have a view with 2 labels on it. The first label is used to show an abbreviation of a name, 2-3 letters. and the second label shows the full name.

The question that I have is if there was a way to dynamically size the label based on the font type, size, and string length given? I ask because I would like the second label close to the first without too much empty space between the two or without the first label overlapping the second.

The reason that this isn't all in one label is because the first label should have a bigger font and different color scheme then the second label.

Any advice is greatly appreciated.

Lofty answered 7/2, 2012 at 18:3 Comment(1)
Follow this link[rob mayoff's answer][1] Thanks [1]: #13206613Lorenalorene
C
64

You can calculate the size of in which your string will appear and then can set frame of your UILabel to that size see following code as a sample -

//Calculate the expected size based on the font and linebreak mode of your label
CGSize maximumLabelSize = CGSizeMake(296,9999);

CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font 
                        constrainedToSize:maximumLabelSize 
                        lineBreakMode:yourLabel.lineBreakMode]; 

//adjust the label the the new height.
CGRect newFrame = yourLabel.frame;
newFrame.size.height = expectedLabelSize.height;
yourLabel.frame = newFrame;

Update -

Use sizeWithAttributes: instead, which now takes an NSDictionary. Pass in the pair with key UITextAttributeFont and your font object like this:

CGSize size = [string sizeWithAttributes:
                       @{NSFontAttributeName:
                         [UIFont systemFontOfSize:17.0f]}];

Check Replacement for deprecated sizeWithFont: in iOS 7? for more details

Calabrese answered 7/2, 2012 at 18:13 Comment(4)
You sir are a savior. I'm still trying to learn the iOS API and how everything is supposed to work.Lofty
@Lofty - Best of Luck! Happy Programming!Calabrese
this part of code: lineBreakMode:yourLabel.lineBreakMode is not for IOS 6Lunch
sizeWithFont is deprecated. Any good alternative with example can really help me..?Minsk
P
16

This will also do the trick and will take into account attributed text

label.attributedText = attrString;
CGSize maximumLabelSize = CGSizeMake(187,CGFLOAT_MAX);
CGSize requiredSize = [label sizeThatFits:maximumLabelSize];
CGRect labelFrame = label.frame;
labelFrame.size.height = requiredSize.height;
label.frame = labelFrame;
Peat answered 9/11, 2012 at 15:47 Comment(4)
This solution is much more sensible. The UILabel should be in charge of the size, not the NSString.Tetter
what is CGFLOAT_MAX ??Happily
It is the highest value a float variable can store.Peat
what will be in place of attrString ?Schaeffer
I
10

'sizeWithFont:' is deprecated: first deprecated in iOS 7.0.

so try sizeWithAttributes

- (void)viewDidLoad
{
    [super viewDidLoad];

    label = [[UILabel alloc] initWithFrame:CGRectMake(20, 40, 300, 20)];

    label.backgroundColor = [UIColor blueColor];

     const CGFloat fontSize = 30;
     UIFont *regularFont = [UIFont systemFontOfSize:fontSize];
     UIColor *foregroundColor = [UIColor blackColor];

     attrs = [NSDictionary dictionaryWithObjectsAndKeys:
     regularFont, NSFontAttributeName,
     foregroundColor, NSForegroundColorAttributeName
     , nil];

     NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc]
     initWithString:@"Test Text"
     attributes:attrs];

     [label setAttributedText:attributedText];
     [self.view addSubview:label];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGSize expectedLabelSize = [label.text sizeWithAttributes:attrs]; // iOS 7 Code <--

    CGRect newFrame = label.frame;
    newFrame.size.width = expectedLabelSize.width;
    label.frame = newFrame;

    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc]
                                                 initWithString:@"Longer Test Text"
                                                 attributes:attrs];

    [label setAttributedText:attributedText];
}
Icky answered 11/9, 2013 at 20:8 Comment(0)
A
8

As sizeWithFont: is deprecated in iOS 7, you need to use sizeWithAttributes (as maver explained here). In order to simplify code, you can add a method that you can reuse like this:

-(CGRect)rectForText:(NSString *)text 
           usingFont:(UIFont *)font 
       boundedBySize:(CGSize)maxSize
{
    NSAttributedString *attrString =
        [[NSAttributedString alloc] initWithString:text
                                        attributes:@{ NSFontAttributeName:font}];

    return [attrString boundingRectWithSize:maxSize
                                    options:NSStringDrawingUsesLineFragmentOrigin
                                    context:nil];
}

And make use of it

CGSize maximumLabelSize = CGSizeMake(280,9999);
UIFont *font = [UIFont systemFontOfSize:20];
CGRect titleRect = [self rectForText:post.title // <- your text here 
                           usingFont:font
                       boundedBySize:maximumLabelSize];
Audio answered 12/3, 2014 at 10:32 Comment(0)
G
7

In addition of Saurabh's answer. I had the same problem and you should add this line
[yourLabel setNumberOfLines:0];
in order the whole text to be shown in X lines.

Gunderson answered 28/2, 2013 at 16:41 Comment(1)
Yes, after setting numberOfLines=0 my problem solved, else I was banging my head agains my screen while implementing Saurabh's solution.Rosenblum

© 2022 - 2024 — McMap. All rights reserved.