Text size that adjusts for any size class - ios

I would like to have the text size change like images when using different size classes with auto layout. Thanks!

If you design for the largest screen, you can use the Autoshrink setting on the label to get the text to fit as the label decreases in size, otherwise you would have to do it via code if you want to both stretch and shrink

try this
-(CGSize)heigtForCellwithString:(NSString *)stringValue withFont:(UIFont*)font{
CGSize constraint = CGSizeMake(250,9999); // Replace 300 with your label width
NSDictionary *attributes = #{NSFontAttributeName: font};
CGRect rect = [stringValue boundingRectWithSize:constraint options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:attributes context:nil];
return rect.size;
}

Related

Find the correct font size for a given text in OBJ C?

I have a UITableView that displays a UILabel in each cell. The text length varies for each item.
[#"Test1",#"Test 245", #Test 568974"]
Now I want to identify the font size that can correctly fit the largest text. In this case I need to find the font size of UILabel that can correctly display the text #Test 568974" with out any truncation.
I have tried using the
adjustsFontSizeToFitWidth
property and also set
Automatically Adjust Font
in story board with minimum font size. But that makes each text to have a different font size.
How to do it?
I finally found the solution,
-(CGFloat)findFontSizeforLabel:(UILabel*)label{
CGFloat minFontSize = 22;
for(Product *product in products){
CGFloat fontSize = 22.0;
while(fontSize > 0){
NSDictionary *attributes = #{NSFontAttributeName: [UIFont fontWithName:#"fontname" size:fontSize]};
CGSize size = [product.title sizeWithAttributes:attributes];
if(size.width < label.frame.size.width - 15){
if(fontSize < minFontSize){
minFontSize = fontSize;
}
break;
}
fontSize--;
}
}
return minFontSize;
}
NSString has a method sizeWithAttributes:
Create a dictionary with the desired text attributes, e.g.:
attrs = [NSDictionary dictionaryWithObject:yourFont forKey: NSFontAttributeName]
and use the method above to get the bounding rectangle. Note that you need to round the returned fractional values to integral values.
With that do a binary search between reasonable font sizes to fit your largest label.
To make label resizable add to interface builder constraints like this:
and set for your table rowHeight to Automatic and estimatedRowheight more than 45:
tableView.estimatedRowHeight = 50
tableView.rowHeight = UITableViewAutomaticDimension
This makes your cell adjust label height.
If you want to get label height programmatically, use:
NSDictionary *attributes = #{NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue" size:14]};
CGRect rect = [textToMeasure boundingRectWithSize:label.frame.size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
This gives you size text for given label size and attributes

Calculate width required to fit text for a multiline UILabel?

I am trying to expand the width of a 2 line UILabel to accommodate a varying amount of text. To do this I am attempting to calculate the width required and then setting it to a width constraint I have set on the label.
However, everything I have done ignores the height/word wrapping, and returns the width required for a single line of text (not 2 lines). Any ideas on how i can find the width needed if 2 or more lines are used in the label?
I have tried using the following methods to find the width:
1.Using boundingRectWithSize to determine the appropriate size for a fixed height (height of 2 lines)
CGSize maxSize = CGSizeMake(MAXFLOAT, fixedHeight);
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
NSDictionary *attributes = #{NSFontAttributeName: self.font, NSParagraphStyleAttributeName: paragraphStyle};
CGRect rect = [self.text boundingRectWithSize: maxSize
options: (NSStringDrawingUsesLineFragmentOrigin)
attributes: attributes
context: nil];
Using the sizeThatFits method to determine the appropriate size.
Thanks!
Make sure fixedHeight you are passing is sufficient enough to accommodate multiple lines. To be safe you can use following
CGSize maxSize = CGSizeMake(300, CGFLOAT_MAX); //where 300 is the width of label
Setting above height will make sure it takes into consideration multiple lines as width is limited. In previous case you were setting width to MAXFLOAT thus width was big enough to accommodate entire content in single line.
It might be silly, but make sure that 'numberOfLines' property of the UILabel is set to 0, so that the size calculation methods can use multiline options.

Create non-constant width for UILabel in Interface Builder using Auto Layout

I have an existing UILabel that I created in Interface Builder, I would like to change its width in code, but I can't because of the auto layout. It's pretty simple, I have width from a CGSize and I wanna set it for the label. Actually my code works perfectly, I can assign the new size to the label, but unfortunately it doesn't redrawn itself. I've tried to use the textRectForBounds:limitedToNumberOfLines:and preferredMaxLayoutWidth without any success or size changes.
float heightIs =
[cell.lbl.text
boundingRectWithSize:cell.lbl.frame.size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{ NSFontAttributeName:cell.lbl.font }
context:nil]
.size.height;
// get the width size of a string
CGSize textSize = [cell.lbl.text sizeWithAttributes:#{NSFontAttributeName:cell.lbl.font}];
CGFloat strikeWidth = textSize.width;
NSLog(#"TEXT WIDTH %f OF STRING %#", strikeWidth, nameString);
CGRect labelFrame = CGRectMake (0, 0, strikeWidth, heightIs);
cell.lbl.frame = labelFrame;
cell.lbl.preferredMaxLayoutWidth = CGRectGetWidth(labelFrame);
NSLog(#"LABEL WIDTH VALUE %f", cell.lbl.frame.size.width);
Could somebody explain me the right way? I'm not sure that where should I start it. Is it an option somewhere in IB or can I do it with code? Or I can delete all code because it can be done only with IB?

Showing an image only if content view of UITextView is larger than its fame

I am doing a project in which I want show an image if the text doesn't fits to the UITextView frame.
I am using the following code
if (self.textView.contentSize.height >= self.TextView.bounds.size.height)
{
self.imageView.hidden = NO;
}
I am using Autolayout also. Does it cause such issues
And one more thing is that, when I print NSLog, the value of contentSize.height was NOT changing according to the text UITextView was showing.
You can use this method to check the height of multi line text according to the font size used
+ (CGSize) calculateLabelHeightWith:(CGFloat)width text:(NSString*)textString
{
CGSize maximumSize = CGSizeMake(width, 9999);
CGSize size = [textString sizeWithFont:[UIFont fontWithName:#"Helvetica" size:24]
constrainedToSize:maximumSize
lineBreakMode:UILineBreakModeWordWrap];
return size;
}
you need to know
width of text feild
string
font
font size
iOS7
CGRect textRect = [text boundingRectWithSize:<text Feild Size>
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[UIFont stuff here]}
context:nil];
CGSize size = textRect.size;
yes, if you assign text to textView and check its size in the next instruction in viewControllers viewDidLoad, it wont work.It will just give you what contentSize you had set.
Check the contentSize in viewDidAppear of ViewController, and it will work.
It worked for me.
Hope this helps,

UILabel - auto-size label to fit text?

Is it possible to auto-resize the UILabel box/bounds to fit the contained text?
(I don't care if it ends up larger than the display)
So if a user enters "hello" or "my name is really long i want it to fit in this box", it is never truncated and the label is 'widened' accordingly?
Please check out my gist where I have made a category for UILabel for something very similar, my category lets a UILabel stretch it's height to show all the content: https://gist.github.com/1005520
Or check out this post: https://stackoverflow.com/a/7242981/662605
This would stretch the height, but you can change it around easily to work the other way and stretch the width with something like this, which is I believe what you want to do:
#implementation UILabel (dynamicSizeMeWidth)
- (void)resizeToStretch{
float width = [self expectedWidth];
CGRect newFrame = [self frame];
newFrame.size.width = width;
[self setFrame:newFrame];
}
- (float)expectedWidth{
[self setNumberOfLines:1];
CGSize maximumLabelSize = CGSizeMake(CGRectGetWidth(self.bounds), CGFLOAT_MAX);
CGSize expectedLabelSize = [[self text] sizeWithFont:[self font]
constrainedToSize:maximumLabelSize
lineBreakMode:[self lineBreakMode]];
return expectedLabelSize.width;
}
#end
You could more simply use the sizeToFit method available from the UIView class, but set the number of lines to 1 to be safe.
iOS 6 update
If you are using AutoLayout, then you have a built in solution. By setting the number of lines to 0, the framework will resize your label appropriately (adding more height) to fit your text.
iOS 8 update
sizeWithFont: is deprecated so use sizeWithAttributes: instead:
- (float)expectedWidth{
[self setNumberOfLines:1];
CGSize expectedLabelSize = [[self text] sizeWithAttributes:#{NSFontAttributeName:self.font}];
return expectedLabelSize.width;
}
Using [label sizeToFit]; will achieve the same result from Daniels Category.
Although I recommend to use autolayout and let the label resize itself based on constraints.
If we want that UILabel should shrink and expand based on text size then storyboard with autolayout is best option. Below are the steps to achieve this
Steps
Put UILabel in view controller and place it wherever you want. Also put 0 for numberOfLines property of UILabel.
Give it Top, Leading and Trailing space pin constraint.
Now it will give warning, Click on the yellow arrow.
Click on Update Frame and click on Fix Misplacement. Now this UILabel will shrink if text is less and expand if text is more.
This is not as complicated as some of the other answers make it.
Pin the left and top edges
Just use auto layout to add constraints to pin the left and top sides of the label.
After that it will automatically resize.
Notes
Don't add constraints for the width and height. Labels have an intrinsic size based on their text content.
Thanks to this answer for help with this.
No need to set sizeToFit when using auto layout. My complete code for the example project is here:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var myLabel: UILabel!
#IBAction func changeTextButtonTapped(sender: UIButton) {
myLabel.text = "my name is really long i want it to fit in this box"
}
}
If you want your label to line wrap then set the number of lines to 0 in IB and add myLabel.preferredMaxLayoutWidth = 150 // or whatever in code. (I also pinned my button to the bottom of the label so that it would move down when the label height increased.)
If you are looking for dynamically sizing labels inside a UITableViewCell then see this answer.
Use [label sizeToFit]; to adjust the text in UILabel
Here's what I am finding works for my situation:
1) The height of the UILabel has a >= 0 constraint using autolayout. The width is fixed.
2) Assign the text into the UILabel, which already has a superview at that point (not sure how vital that is).
3) Then, do:
label.sizeToFit()
label.layoutIfNeeded()
The height of the label is now set appropriately.
I created some methods based Daniel's reply above.
-(CGFloat)heightForLabel:(UILabel *)label withText:(NSString *)text
{
CGSize maximumLabelSize = CGSizeMake(290, FLT_MAX);
CGSize expectedLabelSize = [text sizeWithFont:label.font
constrainedToSize:maximumLabelSize
lineBreakMode:label.lineBreakMode];
return expectedLabelSize.height;
}
-(void)resizeHeightToFitForLabel:(UILabel *)label
{
CGRect newFrame = label.frame;
newFrame.size.height = [self heightForLabel:label withText:label.text];
label.frame = newFrame;
}
-(void)resizeHeightToFitForLabel:(UILabel *)label withText:(NSString *)text
{
label.text = text;
[self resizeHeightToFitForLabel:label];
}
#implementation UILabel (UILabel_Auto)
- (void)adjustHeight {
if (self.text == nil) {
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.bounds.size.width, 0);
return;
}
CGSize aSize = self.bounds.size;
CGSize tmpSize = CGRectInfinite.size;
tmpSize.width = aSize.width;
tmpSize = [self.text sizeWithFont:self.font constrainedToSize:tmpSize];
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, aSize.width, tmpSize.height);
}
#end
This is category method. You must set text first, than call this method to adjust UILabel's height.
You can size your label according to text and other related controls using two ways-
For iOS 7.0 and above
CGSize labelTextSize = [labelText boundingRectWithSize:CGSizeMake(labelsWidth, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{
NSFontAttributeName : labelFont
}
context:nil].size;
before iOS 7.0 this could be used to calculate label size
CGSize labelTextSize = [label.text sizeWithFont:label.font
constrainedToSize:CGSizeMake(label.frame.size.width, MAXFLOAT)
lineBreakMode:NSLineBreakByWordWrapping];
// reframe other controls based on labelTextHeight
CGFloat labelTextHeight = labelTextSize.height;
If you do not want to calculate the size of the label's text than you can use -sizeToFit on the instance of UILabel as-
[label setNumberOfLines:0]; // for multiline label
[label setText:#"label text to set"];
[label sizeToFit];// call this to fit size of the label according to text
// after this you can get the label frame to reframe other related controls
Add missing constraints in storyboard.
Select UILabel in storyboard and set the attributes "Line" to 0.
Ref Outlet the UILabel to Controller.h with id:label
Controller.m and add [label sizeToFit]; in viewDidLoad
the sizeToFit() method doesn't play well with constraints, but as of iOS 9 this is all you need -
label.widthAnchor.constraint(equalToConstant: label.intrinsicContentSize.width).activate()
I had a huge problems with auto layout.
We have two containers inside table cell. Second container is resized depending on Item description (0 - 1000 chars), and row should be resized based on them.
The missing ingredient was bottom constraint for description.
I've changed bottom constraint of dynamic element from = 0 to >= 0.
Fits everytime! :)
name.text = #"Hi this the text I want to fit to"
UIFont * font = 14.0f;
CGSize size = [name.text sizeWithAttributes:#{NSFontAttributeName: font}];
nameOfAssessment.frame = CGRectMake(400, 0, size.width, 44);
nameOfAssessment.font = [UIFont systemFontOfSize:font];
you can show one line output then set property Line=0 and show multiple line output then set property Line=1 and more
[self.yourLableName sizeToFit];
There's also this approach:
[self.myLabel changeTextWithAutoHeight:self.myStringToAssignToLabel width:180.0f];

Resources