Hot to get UILabel Width using AutoLayout? - ios

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.

Related

Vertical Shift UILabel Text Without Affecting Background

I've been trying to figure out how to vertically align my UILabel text to the top or bottom. The problem is, I have an image behind it which also gets shifted with the text.
Is there a way to keep the background color/image in place, but only shift the text up or down?
Here's the current code:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (!self) return nil;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0,
0,
frame.size.width,
frame.size.height)];
label.textAlignment = NSTextAlignmentLeft;
label.font = [UIFont fontWithName:#"AvenirNext-Bold" size:12];
label.backgroundColor = [UIColor clearColor];
[self addSubview:label];
self.numberLabel = label;
self.layer.cornerRadius = 3;
return self;
}
I've been following this tutorial, but it shifts everything, including my label background.
Vertically align text to top within a UILabel
find the height of the text.
Use another view to show image.
Set frame of label relative image view with height of the text and whatever position you want to set for label.
ON the label if you're not using auto layout use:
[YOUR_LABEL sizeToFit];
This will resize your label to fit the text.
What is the background image ? A separate UIImageView ? How are you setting this image ?

UILabel view disappear when the height greater than 8192

Assigning large string to UILabel. And, adding this label into a scroll view.
The UILabel disappear when the UILabel height larger than 8192pt (which is 2^13).
Is this an iOS bug?
And should I use other implementation to render such amount of string?
Should I use table view with cell?
UPDATE
The code that will display the UILabel:
UILabel *label = [[UILabel alloc] init];
label.backgroundColor = [UIColor clearColor];
label.text = rumor.displayText;
label.frame = CGRectMake(0, 0, self.view.frame.size.width, 8192);
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0;
And the code that UILabel does disappear
UILabel *label = [[UILabel alloc] init];
label.backgroundColor = [UIColor clearColor];
label.text = rumor.displayText;
label.frame = CGRectMake(0, 0, self.view.frame.size.width, 8193);
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0;
First of all - it doesn't have to be a bug. It is just undefined behavior. Note that with every component, there will be some upper size limit when the component stops working correctly . 8192 points seems to be a low limit but still it's about 8 times the iPad screen in portrait mode.
You are not supposed to make views that big. Note that UIViews are often rendered into memory and buffered, to make redrawing faster. With 8192 height, the buffer will have to be very big.
Splitting the text into several UILabels (e.g. by paragraph) would definitely be an improvement.
See https://stackoverflow.com/a/1494496/669586
I ran into this same issue with UITextViews, and came up with a fairly effective solution.
If you'd like to see it, check out my answer here!:
https://stackoverflow.com/a/37147533/2155673
It should be fairly easily to adapt for UILabels.

Clipping of UILabel when adjustsFontSizeToFitWidth

When I add text to a label with the adjustsFontSizeToFitWidth set to YES the text is no longer centred vertically and eventually clips the text at the bottom of the label frame. For a large amount of text it will eventually disappear off the bottom of the label.
This is what happens if you add less text:
This is clipped as I would expect it (i.e. the font size did not reduce, the text was vertically centred in the label and clipped on the top and bottom.
Here is the code to reproduce:
- (void)loadView {
[super loadView];
self.view.backgroundColor = [UIColor blueColor];
testLabel = [[UILabel alloc] init];
testLabel.font = [UIFont boldSystemFontOfSize:172];
testLabel.textColor = [UIColor blackColor];
testLabel.adjustsFontSizeToFitWidth = YES;
testLabel.numberOfLines = 1;
testLabel.frame = CGRectMake(50, 50, 300, 100);
testLabel.text = #"123";
[self.view addSubview:testLabel];
}
Should this happen? And how do I get my label to centre vertically irrespective of the number of characters in my label.
Add
testLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
to your code to vertical-center the text on font scale.
Would also like add that adjustsFontSizeToFitWidth doesn't work too well with attributed text, so add your attributes to the label instead of the attributed text if you can. This worked for me.

Programmatically created UILabel not working in iOS 6

I programmatically create a few UILabels in my app. In iOS 5 this code worked fine.
In iOS 6 the labels simply don't seem to appear on the screen.
I don't see any warnings, the code definitely executes, but no label.
I've tried searching for similar issues but can't find anything. My labels have literally just disappeared.
Any help appreciated.
float popUpWidth = 700.0
//Add label
UILabel *label;
label = [[UILabel new] initWithFrame:CGRectMake(0,0,popUpWidth,50)];
label.text = #"Notes";
label.textAlignment = UITextAlignmentCenter;
label.backgroundColor = [UIColor blackColor];
label.textColor = [UIColor whiteColor];
//Add label to view
[self.view addSubview:label];
The problem is you are creating a label twice as wide as the devices screen, and setting a small amount of text to be centered thus causing the text to be off screen. Remember CGRect uses points not pixels. Additionally, I tested your code and had to replace "new" with "alloc" for it to work properly, I suggest you do the same.
The full correct line would be:
label = [[UILabel alloc] initWithFrame:CGRectMake(0,0,popUpWidth,50)];
Calling [UILabel new] is like calling [[UILabel alloc] init] so you should change your code like this:
label = [[UILabel alloc] initWithFrame:CGRectMake(0,0,popUpWidth,50)];

UILabel auto resize on basis of text to be shown

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)

Resources