UILabel auto resize on basis of text to be shown - ios

I'm working on an application, in which I'm required to autoresize the text area on basis of text to be displayed.
Firstly, I'm not sure for this either I should use UILabel (Logically is the best choice for displaying static text, which is in my case) or UITextView.
How I wish to use it?
I want to simply init my Label or text view for that matter with Text.
Instead I define the frame first and then restrict my text in that area.
If you can suggest the right solution, that will be a great help.
I went through documentation and other references but didn't find much which could help me here or I could've overlooked it.

The sizeToFit method worked just great.
I did following.
UILabel *testLabel =[[UILabel alloc] initWithFrame:CGRectMake(6,3, 262,20 )]; // RectMake(xPos,yPos,Max Width I want, is just a container value);
NSString * test=#"this is test this is test inthis is test ininthis is test inthis is test inthis is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...this is test in uilabel ...";
testLabel.text = test;
testLabel.numberOfLines = 0; //will wrap text in new line
[testLabel sizeToFit];
[self.view addSubview:testLabel];

You can find a text size with :
CGSize textSize = [[myObject getALongText]
sizeWithFont:[UIFont boldSystemFontOfSize:15]
constrainedToSize:CGSizeMake(maxWidth, 2000)
lineBreakMode:UILineBreakModeWordWrap];
then you can create your UILabel like that :
UILabel * lbl = [[UILabel alloc] initWithFrame:CGRectMake(0,0,textSize.width, textSize.height];
[lbl setNumberOfLines:0];
[lbl setLineBreakMode:UILineBreakModeWordWrap];
[lbl setText:[myObject getALongText]];

In Swift:
testLabel = UILabel(frame: CGRectMake(6, 3, 262, 20))
testLabel.text = test
testLabel.numberOfLines = 0
testLabel.sizeToFit()
In Objective C
UILabel *testLabel = [[UILabel alloc] initWithFrame: CGRectMake(6, 3, 262, 20)]];
testLabel.text = test;
testLabel.numberOfLines = 0;
[testLabel sizeToFit];

If you want to resize the UILabel only in height, use this:
#property (nonatomic, weak) IBOutlet UILabel *titleLabel;
CGRect titleLabelBounds = self.titleLabel.bounds;
titleLabelBounds.size.height = CGFLOAT_MAX;
// Change limitedToNumberOfLines to your preferred limit (0 for no limit)
CGRect minimumTextRect = [self.titleLabel textRectForBounds:titleLabelBounds limitedToNumberOfLines:2];
CGFloat titleLabelHeightDelta = minimumTextRect.size.height - self.titleLabel.frame.size.height;
CGRect titleFrame = self.titleLabel.frame;
titleFrame.size.height += titleLabelHeightDelta;
self.titleLabel.frame = titleFrame;
Now you can use titleLabelHeightDelta to layout other views depending on your label size (without using autolayout).

I'm not sure I totally understand the question, but you can use the sizeToFit method on a UILabel (the method is inherited from UIView) to change the size according to the label text.

The easiest way to find the no. of lines depending on text. You can use this code:
ceil(([aText sizeWithFont:aFont].width)/self.bounds.size.width-300);
it returns some float value.
[lbl setNumberOfLines:floatvalue];

Please note that with autolayout call sizeToFit won't change size, because it will be changed later by autolayout calculations. In this case you need to setup proper height constraint for your UILabel with "height >= xx" value.

Because you're going to use this solution countless times in your app, do the following:
1) Create a directory called extensions and add a new file inside called UILabel.swift with the following code:
import UIKit
extension UILabel {
func resizeToText() {
self.numberOfLines = 0
self.sizeToFit()
}
}
2) In your app code, define the label width you want and just call resizeToText():
label.frame.size.width = labelWidth
label.resizeToText()
This will maintain width while increasing the height automatically.

try bellow code, it works for multiline
self.labelText.text = string;
self.labelText.lineBreakMode = NSLineBreakByWordWrapping;
self.labelText.numberOfLines = 0;

You can change the size of label based on length of the string by, using this function
func ChangeSizeOfLabel(text:String) -> CGSize{
let font = UIFont(name: "HelveticaNeue", size: 12)!
let textAttributes = [NSFontAttributeName: font]
let size = text.boundingRectWithSize(CGSizeMake(310, 999), options: .UsesLineFragmentOrigin, attributes: textAttributes, context: nil)
let adjustSize = CGSizeMake(size.width, size.height)
return adjustSize
}
and use it like this :
let
showLabel.frame = CGRectMake(x, y, width , self.ChangeSizeOfLabel("Hello , Height is changing dynamically.....").height)

Related

Create UILabel programmatically and set its position

I want to create a UILabel programmatically from a button click and set its position to the x,y coordinates: (50,50).
The text size can vary between 300 characters to 2,000 characters so I'm using:
[myLabel sizeToFit]
to set the width and height of the label.
This is my code so far:
- (IBAction)createLabel:(id)sender { //create label on button click
UILabel *label;
[label sizeToFit]; //set width and height of label based on text size
//position label
CGRect frame = label.frame;
frame.origin = CGPointMake(50, 50);
label.frame = frame;
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByCharWrapping;
label.text = #"This is where the text goes";
[self.view addSubview:label]; //add label to view
}
It doesn't give me any errors when I run the program, but when I press the button to create a label, nothing shows up.
You're not actually creating a label.
UILabel *label;
Just declares a variable, you never initialise it or assign a value to it. You either need a reference to an existing label or you need to create one using initWithFrame:
Also, sizeToFit should be done after you've assigned the text.

Getting the actual height of a UITextView

I have a NSAttributedString being passed into a UITextView:
NSAttributedString *str = #"A really long string ... that continues for awhile";
The string is random in length and I want to pass it into a UITextView.
myTextView.attributedText = str;
I need the width of the UITextView to be 300 but how do I find the heigt?
If I'm not mistaken you can do this:
[myTextView sizeToFit];
And then retrieve the height from myTextView.bounds.size.height. Note though that UITextViews also add some padding to the edges so you may want to subtract that from the height.
If I am mistaken than here is an alternative that is less clean but will work:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300.f, yourMaxHeight)];
label.attributedText = myTextView.attributedText;
label.numberOfLines = INFINITY;
[label sizeToFit];
CGFloat height = label.bounds.size.height;
This of course does not include the UITextView padding.

Width of UILabel created programmatically

I'm trying to create a UILabel programmatically that fits it's content.
The best I could do was to use the NSString's method sizeWithAtributes to get it's content's required width and then apply a constraint that fixes the width to that value.
Is this the way it is supposed to be done using autolayout?
if you need some with aoutolayouts, i try comment:
UILabel *testLabel = [UILabel new];
[testLabel setFont:[UIFont systemFontOfSize:16]];
[testLabel setText:#"Test text for size context"];
[testLabel setTextAlignment:NSTextAlignmentLeft];
[testLabel setNumberOfLines:0]; //0 - infiniy lines if not enough space more
[testLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; // Autolayout rule: The higher the priority, the more important hold the text.. by horizontal
[testLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];//some like above but verticale
[testLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];// reverse like Hugging but Compression. then lower priority then text croping.
[testLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisVertical];
[testLabel preferredMaxLayoutWidth:200];//Start new line each 200 points width
[testLabel setPreferredMaxLayoutWidth:YES];// resize Font size by label size.
[testLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; // Disable autolaresize, enable autolayouts
At First read the best answer for any question about UILabel
And also by using following code you can create dynamic size of UILabel
UILabel *myLabelName = [[UILabel alloc] init];
myLabelName.backgroundColor = [UIColor redColor];
[myLabelName setFont: [UIFont fontWithName:#"OpenSans" size:13]]; // set font and it's size as per your requirement.
myLabelName.textAlignment = NSTextAlignmentLeft;
myLabelName.frame = CGRectMake(lblComplainTitle.frame.origin.x + lblComplainTitle.frame.size.width + 7, lblComplainTitle.frame.origin.y +2, 160, 20);
myLabelName.text = #"This is my testing text, This is my testing text, This is my testing text, This is my testing text, This is my testing text, This is my testing text, This is my testing text, This is my testing text, This is my testing text, This is my testing text.";
myLabelName.textColor = [UIColor blackColor];
[self setDynamicHeightOfLabel:myLabelName withLblWidth:160 andFontSize:13]; // here in this function you need to pass object of label with width (as you wabt) and font size
[self.view addSubview:myLabelName];
Code of function, name is setDynamicHeightOfLabel:withLblWidth:andFontSize
-(void) setDynamicHeightOfLabel:(UILabel *) myLabel withLblWidth:(CGFloat) width andFontSize:(int) fontSize
{
CGSize myLabelSize = CGSizeMake(width, FLT_MAX);
CGSize expecteingmyLabelSize = [myLabel.text sizeWithFont:myLabel.font constrainedToSize:myLabelSize lineBreakMode:myLabel.lineBreakMode];
CGRect lblFrame = myLabel.frame;
lblFrame.size.height = expecteingmyLabelSize.height;
myLabel.frame = lblFrame;
int addressLine = myLabel.frame.size.height/fontSize;
myLabel.numberOfLines = addressLine;
}
I create function because you can create any label with dynamic size without use of repeated code.
There is a couple of steps that you have to do to achieve this using autolayout.
Set layout constrains for the label.
Set height constraint with low priority.
Set numberOfLines to 0 to allow multiline text.
Set preferredMaxLayoutWidth for the label.
The preferredMaxLayoutWidth is used by label to calculate its height.
This property affects the size of the label when layout constraints
are applied to it. During layout, if the text extends beyond the width
specified by this property, the additional text is flowed to one or
more new lines, thereby increasing the height of the label.
Hi you can manage the width of lable by doing so programatically,
CGRect frame;
frame =self.yourLabel.frame;
frame.size.width +=20;
self.yourLabel.frame=frame;
Thanks

Hot to get UILabel Width using AutoLayout?

I might missing something very trivial here, but I can't figure out how to get the width of my UILabel. Note that is it being added programatically, and the it's size fits the text inside it (the text vary from 2 to 35 characters). It automatically fits the right width of it's content, but I need to get the width.
My code to add it to the screen:
UILabel *textLabel = [[UILabel alloc] init];
textLabel.text = textInputFromUser;
textLabel.textColor = [UIColor whiteColor];
textLabel.backgroundColor = [UIColor colorWithRed:40.0/255.0 green:40.0/255.0 blue:40.0/255.0 alpha:0.95];
textLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:textLabel];
Note that the following code (with "Bounds"/"Frame") always returns 0.00):
NSLog(#"textlabel width: %f", textLabel.bounds.size.width);
You can only find out the size after the first layout pass. So either wait for that or call
[textLabel layoutIfNeeded];
to layout it immediately. After that the frame should be set to the right value.
Since no one else answered, I'll throw in my two cents…
I assume the reason you're unable to get the frame of the label is because the frame hasn't technically been instantiated; but nonetheless, maybe just getting the size of the content would be sufficient for your needs.
Here's a post explaining how to use boundingRectWithSize:options:attributes:context: to get the size of the text in your label: https://stackoverflow.com/a/18961502/2274694
Try initializing the label with a dummy frame like so:
UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0,1,1)];
textLabel.text = textInputFromUser;
[textLabel sizeToFit];
or you could try:
UILabel *textLabel = [[UILabel alloc] initWithString:textInputFromUser];
for swift I had to add following code block to get correct width for UILabel:
private var infoLabel = UILabel()
infoLabel.translatesAutoresizingMaskIntoConstraints = false
infoLabel.frame = .zero
infoLabel.font = UIFont.boldSystemFont(ofSize: 14)
infoLabel.numberOfLines = -1
infoLabel.text = "infoText"
infoLabel.sizeToFit()
to get correct width:
let infoWidth = infoLabel.frame.size.width
I also added correct constraints to my label (which is infoLabel) according to design given to me.

Center vertically in UILabel with autoshrink

This is a little different from all the other "How do I center the text in a UILabel" questions here...
I have a UILabel with some text in it, I want to center the text vertically in the UILabel. What's the big deal, right? That's the default. The problem comes because my text is dynamic and I have autoshrink turn on. As the text grows larger, the font size shrinks. You get this behavior.
Notice that the font baseline has not moved, I want it to move so the numbers are centered vertically in the UILabel's frame.
Easy, right? I just remember the frame's original center in viewDidLoad
self.workoutTimeCenter = _workoutTimeLabel.center;
and then I call sizeToFit after I change the the text, right?
[_workoutTimeLabel sizeToFit];
_workoutTimeLabel.center = _workoutTimeCenter;
Well, sizeToFit did, I guess, exactly what it was supposed to do, resize the frame so the text fits without shrinking!
How can I vertically center the text in a UILabel while respecting baselines and autoshrink? (Note, an iOS5 and later solution is fine and I can even deal with an iOS6 and later solution.)
In my experience you can just set the -[UILabel baselineAdjustment] property to UIBaselineAdjustmentAlignCenters to achieve the effect you're describing.
From the docs:
baselineAdjustment
Controls how text baselines are adjusted when text
needs to shrink to fit in the label.
#property(nonatomic) UIBaselineAdjustment baselineAdjustment
Discussion
If the adjustsFontSizeToFitWidth property is set to YES,
this property controls the behavior of the text baselines in
situations where adjustment of the font size is required. The default
value of this property is UIBaselineAdjustmentAlignBaselines. This
property is effective only when the numberOfLines property is set to
1.
and
UIBaselineAdjustmentAlignCenters
Adjust text based relative to the center of its bounding box.
EDIT: adding a full view-controller that demonstrates this:
#interface TSViewController : UIViewController
#end
#implementation TSViewController
- (void) addLabelWithFrame: (CGRect) f baselineAdjustment: (UIBaselineAdjustment) bla
{
UILabel* label = [[UILabel alloc] initWithFrame: f];
label.baselineAdjustment = bla;
label.adjustsFontSizeToFitWidth = YES;
label.font = [UIFont fontWithName: #"Courier" size: 200];
label.text = #"00";
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor = [UIColor lightGrayColor];
label.userInteractionEnabled = YES;
[self.view addSubview: label];
UIView* centerline = [[UIView alloc] initWithFrame: CGRectMake(f.origin.x, f.origin.y+(f.size.height/2.0), f.size.width, 1)];
centerline.backgroundColor = [UIColor redColor];
[self.view addSubview: centerline];
UITapGestureRecognizer* tgr = [[UITapGestureRecognizer alloc] initWithTarget: self action: #selector(onTap:)];
[label addGestureRecognizer: tgr];
}
- (void) viewDidLoad
{
[super viewDidLoad];
[self addLabelWithFrame: CGRectMake(0, 0, 320, 200)
baselineAdjustment: UIBaselineAdjustmentAlignCenters];
[self addLabelWithFrame: CGRectMake(0, 220, 320, 200)
baselineAdjustment: UIBaselineAdjustmentAlignBaselines];
}
- (void) onTap: (UITapGestureRecognizer*) tgr
{
UILabel* label = (UILabel*)tgr.view;
NSString* t = [label.text stringByAppendingString: #":00"];
label.text = t;
}
#end
when working in IB, be sure to set align baselines to center
Note: line break CANNOT be word wrap for this to work, so it will NOT work multiline (good to set the line break to Truncate tail)
-(void)fitVerticallyToLabel:(UILabel *)lbl
{
CGFloat fontSize = lbl.frame.size.width / lbl.text.length;
[lbl setFont:[UIFont fontWithName:#"Helvetica-Bold" size:fontSize]];
CGRect rect = lbl.frame;
rect.origin.y += rect.size.height - fontSize;
rect.size.height = fontSize;
[lbl setFrame:rect];
}
How to Use: Call this method after setting the text to your label.
label.text = #"text";
[self fitVerticallyToLabel:label];
Note: I ahev taken UILabel from xib. You can take it programmatically too in that case you will have to set its text alignment NSTextAlignMentCenter
Try to implement this logic:
-(void)adjustLabel1Text1:(NSString *)text1
{
UILabel *lbl_first = [UIFont fontWithName:#"Helvetica" size:12];
text1 = [text1 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
float hedingLblHeight = [self calculateHeightOfTextFromWidth:text1 : [UIFont fontWithName:#"Helvetica" size:12] :118 :UILineBreakModeWordWrap];
lbl_first.text=text1;
[lbl_first setFrame:CGRectMake(lbl_first.frame.origin.x, lbl_first.frame.origin.y, 118, hedingLblHeight)];
lbl_first.lineBreakMode = UILineBreakModeWordWrap;
lbl_first.numberOfLines = 0;
[lbl_first sizeToFit];
//////////Adjust the lable or any UIControl below this label accordingly.
float endResultHeight=[self calculateHeightOfTextFromWidth:text2 : [UIFont fontWithName:#"Helvetica" size:15] :299 :UILineBreakModeWordWrap];
if(hedingLblHeight>secondImgTitleHeight)
{
[lbl_endResult setFrame:CGRectMake(lbl_endResult.frame.origin.x, lbl_first.frame.origin.y+lbl_first.frame.size.height+5, 299, endResultHeight)];
}
else
{
[lbl_endResult setFrame:CGRectMake(lbl_endResult.frame.origin.x, lbl_first.frame.origin.y+lbl_first.frame.size.height+5, 299, endResultHeight)];
}
lbl_endResult.lineBreakMode=UILineBreakModeWordWrap;
lbl_endResult.numberOfLines = 0;
[lbl_endResult sizeToFit];
}
-(float) calculateHeightOfTextFromWidth:(NSString*)text : (UIFont*) withFont:(float)width :(UILineBreakMode)lineBreakMode
{
CGSize suggestedSize = [text sizeWithFont:withFont constrainedToSize:CGSizeMake(width, FLT_MAX) lineBreakMode:lineBreakMode];
return suggestedSize.height;
}
It has helped me a lot.Hope it works for you.
Try
yourLabel.textAlignment = UITextAlignmentCenter;

Resources