ios Dynamic sizing labels - ios

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.

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

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;

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

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

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.

Related

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;

iOS 8 sizeThatFits for UITextView text not returning correct height (AutoLayout)

I'm trying to vertically center a UITextView using the appropriate height retrieved from sizeThatFits. There are a plethora of other answers that suggest this is the most appropriate way of calculating this.
(Note that I've tried it both with plain and attributed strings, and both exert the same behavior).
No matter what I try (even using attributed strings and setting the font size or line height to something bigger or smaller) it always only shows a certain truncated number of characters of text (in this case, 3 lines, and it's always exactly the same). What am I missing?
_textView.text = [_collectionDescription lowercaseString];
_textView.font = [UIFont fontLight:22];
_textView.textColor = [UIColor whiteColor];
_textView.textAlignment = NSTextAlignmentCenter;
_constraintTextViewHeight.constant = ceilf([_textView sizeThatFits:CGSizeMake(_textView.frame.size.width, FLT_MAX)].height);
[_textView setNeedsDisplay];
[_textView updateConstraints];
As always with AutoLayout, you have to do:
[_textInfoView layoutIfNeeded];
(don't even need the setNeedsDisplay at all).
So, fully working:
_textView.text = [_collectionDescription lowercaseString];
_textView.font = [UIFont fontLight:22];
_textView.textColor = [UIColor whiteColor];
_textView.textAlignment = NSTextAlignmentCenter;
_constraintTextViewHeight.constant = ceilf([_textView sizeThatFits:CGSizeMake(_textView.frame.size.width, FLT_MAX)].height);
[_textView layoutIfNeeded];
[_textView updateConstraints];
Instead of using sizeThatFits: method, you may use following method:
well you can try this:
NSDictionary *attributes = #{NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue" size:14]};
// NSString class method: boundingRectWithSize:options:attributes:context is
// available only on ios7.0 sdk.
NSString *text = _textView.text;
CGRect rect = [text boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
_constraintTextViewHeight.constant = CGRectGetHeight(rect)
This method also considers line breaks in string text

Create and place a UILabel to fix my text with a dynamic height

I have a:
NSString *text = #"A string of x letters of text goes here";
I then have a UILabel that with a specific font and font sie and the label will have a width of 310.
How do I create it so the height is dynamic? I want it to fit perfectly.
Try this,
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 35)];//set the correct width here
NSString *text = #"A string of x letters of text goes here";
label.text = text;
CGSize constrainedSize = CGSizeMake(label.frame.size.width , 9999);
//TODO:change the font properties to yourown
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"HelveticaNeue" size:11.0], NSFontAttributeName,
nil];
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:text attributes:attributesDictionary];
CGRect requiredHeight = [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];
if (requiredHeight.size.width > label.frame.size.width) {
requiredHeight = CGRectMake(0,0, label.frame.size.width, requiredHeight.size.height);
}
CGRect newFrame = label.frame;
newFrame.size.height = requiredHeight.size.height;
label.frame = newFrame;
If you are using auto layouts. Just set the numberOflines = 0 . Note : Do not pin the hight of the label.Based on the other constraints it will automatically grow its size to fit the string.

Use sizeToFit with lineSpacing

I have a UILabel with several lines. The text is set dynamically, and my label height too, with this native method :
[myLabel sizeToFit];
I have an other method that sets the line spacing in my label :
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:#"My long dynamic text"];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:5];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])];
myLabel.attributedText = attributedString;
The problem is that even if I set the line spacing first, and then call sizeToFit, the new height of my label is to small. It doesn't take in count the line spacing.
It really is a problem as my label is in a UIScrollView and I need the right height.
For getting size of label dynamically based on text length use this method:
/*! Returns the size of the label to display the text provided
#param text
The string to be displayed
#param width
The width required for displaying the string
#param fontName
The font name for the label
#param fontSize
The font size for the label
*/
- (CGSize)getSizeForText:(NSString *)text maxWidth:(CGFloat)width font:(NSString *)fontName fontSize:(float)fontSize {
CGSize constraintSize;
constraintSize.height = MAXFLOAT;
constraintSize.width = width;
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:fontName size:fontSize], NSFontAttributeName,
nil];
CGRect frame = [text boundingRectWithSize:constraintSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributesDictionary
context:nil];
CGSize stringSize = frame.size;
return stringSize;
}
Try using – boundingRectWithSize:options:context: method of the NSMutableAttributedString. Refer the Apple Docs for more info.

How to adjust the UILabel width according to the String

I have a UITableView, filled with custom cells. The custom cell has many labels. One label it takes different size strings from the db. What I want is for the next label to start right after the first label (at the end of the string of first lable). I used this code:
cell.Manufactlbl.adjustsFontSizeToFitWidth=YES;
CGSize lLabelSIze = [coffeeObj.price sizeWithFont: cell.Manufactlbl.fontforWidth:cell.Manufactlbl.frame.size.width lineBreakMode:cell.Manufactlbl.lineBreakMode];
cell.Manufactlbl.frame = CGRectMake(cell.Manufactlbl.frame.origin.x, cell.Manufactlbl.frame.origin.y, cell.Manufactlbl.frame.size.width, lLabelSIze.height);
cell.Manufactlbl.font=[UIFont systemFontOfSize:12];
cell.Manufactlbl.text=coffeeObj.price;
cell.Typelbl.frame=CGRectMake(cell.Manufactlbl.frame.origin.x + cell.Manufactlbl.frame.size.width, cell.Typelbl.frame.origin.y, cell.Typelbl.frame.size.width, cell.Typelbl.frame.size.height);
cell.Typelbl.font=[UIFont systemFontOfSize:12];
cell.Typelbl.text=coffeeObj.instrument;`
But this does not work.
Try this.
CGSize size = [#"Your string"
sizeWithFont:[UIFont fontWithName:#"TimesNewRomanPS-BoldMT" size:22]
constrainedToSize:CGSizeMake(500, CGFLOAT_MAX)];
_Lable.frame = CGRectMake(05,05, 50, size.height);
hope it's helpful for you..
You can do something like this: size each label to fit (makes the label just big enough for the text), and then set the frame of each label to be dependent on the others. for example:
[labelOne sizeToFit];
[labelTwo sizeToFit];
labelTwo.frame = CGRectMake(CGRectGetMaxX(labelOne.frame), labelTwo.origin.y, labelTwo.frame.size.width, labelTwo.frame.size.height);
google NS(Attributed)String+Geometrics it solves it
Try this code :
NSString *text1 = #"example text1 ";
CGSize maximumLabelSize = CGSizeMake(236,9999);
CGSize expectedLabelSize = [text1 sizeWithFont:[UIFont systemFontOfSize:12]
constrainedToSize:maximumLabelSize
lineBreakMode:UILineBreakModeCharacterWrap];
UILabel *label1 = [[UILabel alloc]initWithFrame:CGRectMake(50 ,0, expectedLabelSize.width, expectedLabelSize.height)];
label1.font = [UIFont systemFontOfSize:12];
label1.text = text1;
NSString *text2 = #"example Text2";
expectedLabelSize = [text2 sizeWithFont:[UIFont systemFontOfSize:12]
constrainedToSize:maximumLabelSize
lineBreakMode:UILineBreakModeCharacterWrap];
UILabel *label2 = [[UILabel alloc]initWithFrame:CGRectMake(label1.frame.origin.x + label1.frame.size.width ,0, expectedLabelSize.width, expectedLabelSize.height)];
label2.font = [UIFont systemFontOfSize:12];
label2.text = text2;
[self.view addSubview:label1];
[self.view addSubview:label2];

Resources