boundingRectWithSize adds extra bottom padding to UILabel - ios

UILabel is created like this:
label = [[UILabel alloc] initWithFrame:CGRectMake(32, 10, 268, 44)];
label.textAlignment = NSTextAlignmentLeft;
label.backgroundColor = [UIColor yellowColor];
label.numberOfLines = 2;
label.lineBreakMode = NSLineBreakByTruncatingTail;
Then to update the label I do this:
label.text = someText;
CGRect frame = label.frame;
NSDictionary *attributes = #{NSFontAttributeName: label.font};
CGRect rect = [someText boundingRectWithSize:CGSizeMake(label.frame.size.width, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
frame.size.height = rect.size.height;
label.frame = frame;
This works fine with the label only has one line of text, but I have a maximum of two lines. When the 2nd line gets truncated, extra bottom padding gets added to the label, which makes it impossible to position the label below it (the red label in the images):
Why does this happen? If it's a bug, is there a workaround?

Try something like this:
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:text attributes:attributes];
UILabel *anotherLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, myLabel.frame.size.width, MAXFLOAT)];
[anotherLabel setAttributedText:attrString];
[anotherLabel setNumberOfLines:2];
[anotherLabel setText:NSTextAlignmentLeft];
[anotherLabel setLineBreakMode:NSLineBreakByTruncatingTail];
[anotherLabel sizeToFit];
[myLabel setAttributedText:attrString];
[myLabel setFrame:CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, [anotherLabel frame].size.height)];

Related

How to add UILabel above UILabel

If i set bottomLabel.text = Chinese character,i can't see the aboveLabel when i run it and if i debug view hierarchy i can see it.so what's the problem?
UILabel *bottomLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 100, 200, 40)];
bottomLabel.backgroundColor = [UIColor redColor];
bottomLabel.text = #"中文";
[self.view addSubview:bottomLabel];
UILabel *aboveLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 60, 30)];
aboveLabel.backgroundColor = [UIColor greenColor];
aboveLabel.text = #"aboveLabel";
[bottomLabel addSubview:aboveLabel];
why dont you use NSMutableAttributedString for this with one LABEL.
NSString *text1 = #"Hello";
NSString *date1 = #" 12.05 Pm\n";
NSString *text2 = #"World";
NSString *date2 = #" 11.00 AM";
self.lbl.numberOfLines = 0;
NSString * str = [text1 stringByAppendingString:date1];
NSString * str2 = [text2 stringByAppendingString:date2];
UIFont *text1Font = [UIFont fontWithName:#"HelveticaNeue-Medium" size:10];
NSMutableAttributedString *attributedString1 = [[NSMutableAttributedString alloc] initWithString: str attributes:#{ NSFontAttributeName : text1Font }];
NSMutableParagraphStyle *paragraphStyle1 = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle1 setAlignment: NSTextAlignmentLeft];
[paragraphStyle1 setLineSpacing:1];
[attributedString1 addAttribute:NSParagraphStyleAttributeName value: paragraphStyle1 range:NSMakeRange(0, [attributedString1 length])];
UIFont *text2Font = [UIFont fontWithName:#"HelveticaNeue-Medium" size:10];
NSMutableAttributedString *attributedString2 = [[NSMutableAttributedString alloc] initWithString: str2 attributes:#{NSFontAttributeName : text2Font }];
NSMutableParagraphStyle *paragraphStyle2 = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle2 setLineSpacing:1];
[paragraphStyle2 setAlignment: NSTextAlignmentLeft];
[attributedString2 addAttribute:NSParagraphStyleAttributeName value: paragraphStyle2 range:NSMakeRange(0, [attributedString2 length])];
[attributedString1 appendAttributedString:attributedString2];
[self.lbl setAttributedText:attributedString1];
because above label is overlap on bottom label like above image so you not display that if you see that label above label x position change then it display.
if x value set 50 then you display bottm label.
You are adding aboveLabel as subview of bottomLabel hence it doesnot get displayed when you assign chinese character to it. You can see it view hierarchy as it is assigned a frame and added as subview. If you want to add one UILabel above UILabel you can add both labels as subview of common parent view.
i.e.
[self.view addSubview:bottomLabel];
[self.view addSubview:aboveLabel];
You are trying to adding aboveLabel inside of bottomLabel.Instead add both into one view or self.view.
UILabel *bottomLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 100, 200, 40)];
bottomLabel.backgroundColor = [UIColor redColor];
bottomLabel.text = #"中文";
[self.view addSubview:bottomLabel];
UILabel *aboveLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, CGRectGetMaxY(bottomLabel.frame)+10, 60, 30)];
aboveLabel.backgroundColor = [UIColor greenColor];
aboveLabel.text = #"aboveLabel";
[self.view addSubview:aboveLabel];
Try this code
Objective - C
UILabel *bottomLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 200, 30)];
bottomLabel.backgroundColor = [UIColor redColor];
bottomLabel.text = #"中文";
[self.view addSubview:bottomLabel];
UILabel *aboveLabel = [[UILabel alloc]initWithFrame:CGRectMake(50, 0, 60, 30)];
aboveLabel.backgroundColor = [UIColor greenColor];
aboveLabel.text = #"abc";
[bottomLabel addSubview:aboveLabel];

UILabel sizeThatFits too wide for 1-line label

I have a label that I'm creating and displaying programmatically. It can be 1 or more lines. I want to the label to be truncated at the end if it's too long. When the label is > 1 line long the following code works fine. Create a blank project and drop this into viewDidLoad to play along at home. Any iOS or tvOS project should do.
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.numberOfLines = 2;
label.lineBreakMode = NSLineBreakByTruncatingTail;
label.backgroundColor = [UIColor blueColor];
[self.view addSubview:label];
NSDictionary *attributes = #{NSFontAttributeName:[UIFont systemFontOfSize:26.0]};
label.attributedText = [[NSAttributedString alloc] initWithString:#"The rain in Spain falls mainly on the plain." attributes:attributes];
CGSize maxLabelSize = CGSizeMake(200, CGFLOAT_MAX);
CGSize requiredSize = [label sizeThatFits:maxLabelSize];
NSLog(#"requiredSize: %#", NSStringFromCGSize(requiredSize));
label.frame = CGRectMake(50.0, 50.0, requiredSize.width, requiredSize.height);
However, if I change numberOfLines to 1 then sizeThatFits returns a size with a width wide enough to fit the entire string even though it's bigger than the width of maxLabelSize.
I can work around this by checking to see if requiredSize.width is greater than maxLabelSize.width, and adjusting appropriately, but I'd like to know why sizeThatFits behaves differently with a 1-line label than with a multi-line label. I would expect a size no greater than 200 with the height the same as the attributed string's line height.
I have no idea why sizeThatFits doesn't work, but another method textRectForBounds:limitedToNumberOfLines: does the trick. Something like
label.numberOfLines = 0;
CGSize requiredSize = [label textRectForBounds:CGRectMake(0, 0, 200, CGFLOAT_MAX) limitedToNumberOfLines:1].size;
UILabel * commlbl;
commlbl=[[UILabel alloc]initWithFrame:CGRectMake(10, commlbl1.bounds.size.height+50, commscroll.bounds.size.width-25, commscroll.bounds.size.height+70)];
[commlbl setFont:[UIFont fontWithName:#"OpenSans-Regular" size:16]];
[commlbl setTextColor:[UIColor whiteColor]];
[commlbl setTextAlignment:NSTextAlignmentCenter];
commlbl.lineBreakMode = NSLineBreakByWordWrapping;
commlbl.numberOfLines = 0;
commlbl.text = [USER_DFT GetUserDefault:#"msgString"];
CGSize maximumLabelSize = CGSizeMake(296, FLT_MAX);
CGSize expectedLabelSize = [commlbl.text sizeWithFont:commlbl.font constrainedToSize:maximumLabelSize lineBreakMode:commlbl.lineBreakMode];
//adjust the label the the new height.
CGRect newFrame = commlbl.frame;
newFrame.size.height = expectedLabelSize.height;
commlbl.frame = newFrame;

UILabel not showing centre align in ios

I am having one problem stuck. I have created UILabel and changed it frame i.e size height as per the content and it is very fine with all the iPhone devices. However my label is not centre align if we are getting just few word, like Adidas, Nike etc.
brandtitlelabel = [[UILabel alloc] init];
brandtitlelabel.backgroundColor = [UIColor clearColor];
brandtitlelabel.textColor = [UIColor commonTextColor];
brandtitlelabel.numberOfLines = 0;
brandtitlelabel.adjustsFontSizeToFitWidth = YES;
brandtitlelabel.minimumScaleFactor = 0.1;
brandtitlelabel.textAlignment = NSTextAlignmentCenter;
brandtitlelabel.lineBreakMode = NSLineBreakByWordWrapping;
brandtitlelabel.font = [UIFont fontWithName:#"HelveticaNeue-Medium" size:30];
NSString *text = #"Adidas";
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:#{NSFontAttributeName:brandtitlelabel.font}];
rect = [attributedText boundingRectWithSize:(CGSize){self.view.frame.size.width, CGFLOAT_MAX} options:NSStringDrawingUsesLineFragmentOrigin context:nil];
rect.origin = CGPointMake(0, 66);
brandtitlelabel.frame = rect;
brandtitlelabel.text = text;
[self.view addSubview:brandtitlelabel];
Try with this.
brandtitlelabel.text = text;
brandtitlelabel.center = CGPointMake(self.view.center.x,brandtitlelabel.center.y);//replace an 'self.view' with your 'superver' on which you want to center.
[self.view addSubview:brandtitlelabel];
Add following line of code at the end after setting the frame.
brandtitlelabel.textAlignment = NSTextAlignmentCenter;
brandtitlelabel.lineBreakMode = NSLineBreakByWordWrapping;

NSString wordwrapping like UILabel NSLineBreakByWordWrapping

I want a wordwrapping for string to just wanted for the dynamic height calculations purpose, because in UILabel NSLineBreakByWordWrapping, counting string height for dynamic purpose is easy to adjust UILabel height please can any buddy let me know the wordwrapping in string ?
CGSize size = CGSizeZero;
NSString *carNameString = cars.name;
carNameString = [carNameString stringByReplacingOccurrencesOfString:#"\n" withString:#"\n\n"];
CGRect f1 = [carNameString boundingRectWithSize:CGSizeMake([[UIScreen mainScreen]bounds].size.width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{ NSFontAttributeName:[UIFont fontWithName:#"Copperplate" size:20] } context:nil];
size = CGSizeMake(f1.size.width, f1.size.height + 1);
Note: I am using iOS Version 6.3
Edit:
Here is the UILabel Code:
[carLabel setBackgroundColor:[UIColor clearColor]];
[carLabel setText:carNameString];
[carLabel setAdjustsFontSizeToFitWidth:YES];
[carLabel setLineBreakMode:NSLineBreakByWordWrapping];
[carLabel setNumberOfLines:0];
[carLabel setTextColor:[UIColor whiteColor]];
You don't seem to use the size you calculated from the bounding rectangle.
Also, I'd advise you use the same font for your label than you used to calculate the bounding rectangle instead of:
[label setAdjustsFontSizeToFitWidth:YES];
This code should work:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
label.numberOfLines = 0;
label.font = [UIFont fontWithName:#"Copperplate" size:20];
label.text = carNameString;
However, your code doesn't provide the initialization of your UILabel and you don't let us know how you set the frame of your label.
If you wish to use it with auto layout, you would have to set translatesAutoresizingMaskIntoConstraints to NO and to use the size calculated from the bounding rect to set the size of your container view.
Here's a sample based on your code describing it:
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
[self.view addSubview:containerView];
UILabel *label = [UILabel new];
label.translatesAutoresizingMaskIntoConstraints = NO;
[containerView addSubview:label];
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[label]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(label)]];
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[label]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(label)]];
label.numberOfLines = 0;
label.font = [UIFont fontWithName:#"Copperplate" size:20];
label.text = carNameString;

UILabel number of lines affecting the bounds size

I am having this peculiar behavior with UILabel. Any numberOfLines works ok, except 1. If I set the number of lines to 1 it ignores the width which I set later.
I don't understand why 1 line screws it up...
here is my code
UILabel *label = [[UILabel alloc] init];
label.backgroundColor = [UIColor greenColor];
label.text = #"here is my label with lots of text to fill, here is my label with lots of text to fill";
label.frame = CGRectMake(20, 20, 100, 0);
CGRect rect = label.frame;
label.numberOfLines = 2;
label.lineBreakMode = NSLineBreakByTruncatingTail;
[self.view addSubview:label];
rect.size.width = 100;
label.frame = rect;
[label sizeToFit];
Use this code:
UILabel *label = [[UILabel alloc] init];
label.backgroundColor = [UIColor greenColor];
label.text = #"here is my label with lots of text to fill, here is my label with lots of text to fill";
label.frame = CGRectMake(20, 20, 100, 0);
label.numberOfLines = 3;
label.lineBreakMode = NSLineBreakByTruncatingTail;
[self.view addSubview:label];
[label sizeToFit];
CGRect rect = label.frame;
rect.size.width = 100;
label.frame = rect;
With numberOfLines = 3:
With numberOfLines = 1:
If you wanna use numberOfLines = 1 in that case your text will be in one line.So please use numberOfLines = 0;
label.numberOfLines = 0;
And there is no need to again define label frame so please remove these statement.
CGRect rect = label.frame;
rect.size.width = 100;
label.frame = rect;
Use this code this is perfect..
UILabel *label = [[UILabel alloc] init];
label.backgroundColor = [UIColor greenColor];
label.text = #"here is my label with lots of text to fill, here is my label with lots of text to fill";
label.frame = CGRectMake(20, 20, 100, 0);
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByTruncatingTail;
[self.view addSubview:label];
[label sizeToFit];
Yes, it doesn't work when numberOfLines=1
I have to add this line at the end to make it work for all cases..
label.width = min(label.width, 100)
Use this as :
UILabel *label = [[UILabel alloc] init];
label.backgroundColor = [UIColor greenColor];
label.text = #"here is my label with lots of text to fill, here is my label with lots of text to fill";
label.numberOfLines = 0;
CGSize labelSize = [label.text sizeWithFont:label.font constrainedToSize:CGSizeMake(100 , 9999) lineBreakMode:label.lineBreakMode];
float lHeight = labelSize.height;
label.frame = CGRectMake(20, 20, 100, lHeight);
label.lineBreakMode = NSLineBreakByTruncatingTail;
[self.view addSubview:label];
EDIT : - (void)sizeToFit
Description :
Resizes and moves the receiver view so it just encloses its subviews.
Call this method when you want to resize the current view so that it uses the most appropriate amount of space. Specific UIKit views resize themselves according to their own internal needs. In some cases, if a view does not have a superview, it may size itself to the screen bounds. Thus, if you want a given view to size itself to its parent view, you should add it to the parent view before calling this method.
// [label sizeToFit];
Hope it helps you.

Resources