If you take a close look an an iMessage conversation cell, you’ll notice that the preview text is always two lines long. This can’t be a hard coded row height because the rows adjust to dynamic type. How can you always force a label to take up a certain number of lines even if there isn’t enough text to do so?
Set the label's numberOfLines to 2 and end the label's text with a linefeed \n. Set the wrapping to word wrap to prevent the ellipses from appearing.
This guarantees that the label text consists of at least 2 lines worth of material. Thus it can never be less than 2 lines, and since the maximum number of lines is 2, it can never be more than 2 lines. Thus it will always be (wait for it) 2 lines.
One way I think this could be possible is having a UIView as a parent of the UILabel.
Fix the height of the UIView based on device size class. Let's say for example 50 points for Width = Compact and Height = Regular.
Embed UILabel in UIView
Set number of Lines = 0 for UILabel
Now match UILabel leading , trailing ,top edge with the superview and leave the height as it is , also don't set the bottom constraints.
Select the superview i.e the UIView and UILabel together and select Equal Heights.
Open the constraint window and change label height less than or equal to SuperView height.
Short Message
Long Message
Height Constraint of the UILabel with respect to SuperView.
Related
cell.bodyText.numberOfLines = 0
cell.bodyText.text = newsBody
cell.bodyText.sizeToFit()
I set the number of lines to 0 because the number of lines can vary (I am retrieving news articles and since every news article is obviously different in length, numberOfLines is 0)
If I do not use sizeToFit() after assinging newsBody to the label, and check the label height (cell.bodyText.frame.size.height), I get really large numbers (when I tested it, an article that had 25 lines of text, the height was apparently 4000). If I use sizeToFitand then check the height, I get 21 no matter how short or long the label is. (21 is the height I set the UILabel in the storyboard).
How can I get an accurate representation of how many lines are in the UILabel or even just the height of the label?
I assume you're doing this work in tableView(_:cellForRowAtIndexPath:). That's not reliable for querying final layout. Try using the delegate method tableView(_:willDisplayCell:forRowAtIndexPath:). That's called immediately before displaying the cell, and is the appropriate place to work out any final layout issues since everything has been applied at that point.
I'm working via the IB and have a UILabel that's stretched almost to the end of the layout. I have it set with Lines=2, because the max amount of lines it should take is 2. However if it's only 1 line long, I would like it to have a vertical justification of top.
Label settings in IB:
Lines:2
Line breaks: Word wrap
In code, in the viewDidLoad method I set the text of the UILabel. However as part of the functionality at a point the text must change. This is my code:
[_main_lbl1 setText:[myUI MAIN_TITLE]]; //Always only 1 line
[_main_lblsub1 setText:[myUI SUB_TITLE]]; //May be 1 or 2 lines
[_main_lblsub1 sizeToFit]; //Causes vertical alignment (I believe)
Whenever I change the text and rerun sizeToFit, the text wrapping becomes totally messed up. Instead of reaching almost the end of the UILabel as set up in the IB, in some cases the text will wrap at little more than half the distance, in some cases it doesn't wrap at all.
Image of layout in IB:
Image of resulting label in simulator:
In the first label it seems to be working ok, the second label doesn't wrap at all.
Is there anything I have to do to keep the text wrapping when changing the UILabel text? Anything else I'm missing?
Note: Updated question to include more detail and pics.
Thanks
The issue is that you're using sizeToFit. Which stretches the label out to fit the text. If you need to change the size you can use:
CGSize maxSize = CGSizeMake(320, 9999); // 999 means it can be as tall as you like
CGSize textSize = [label.text sizeWithFont:label.font
constrainedToSize:maxSize];
label.size = textSize;
You shouldn't have to do anything special. It will automatically wrap the text to fit when you change it. Otherwise the text would run out of the text labels bounds (which is not what you want). Your problem is that sizeToFit permanently changes the frame of the label. It makes it as small as possible while still showing the text. You are having it resize its frame to the original text and then you are changing the text so it is no longer sized properly. You should reset the frame back to it's original, change the text, and finally call size to fit again.
In viewDidLoad:
self.originalFrame = self.mainLabelSub1.frame;
Then in viewWillAppear:
self.mainLabel1.frame = self.originalFrame;
self.mainLabel1.text = #"New Text";
Note:
A good way to see the borders of the text label to get an idea for the wrapping potential is to temporary set the background of the label to something like magentaColor that stands out.
I have an UIView that it should contains UILabels, and these UILabels are not fixed if an UILabel is nil, i don't display it, and if is not i must resize the UILabel to fit text (they can be 2 ligne) and put it under another UILabel, and after i must resize the UIView container for the amount of this UILabels. this the Screen Shot that i want to do programmatically:
UILabels can fit large amounts of text by automatically making the font smaller (see the minimum font size value in the Interface Builder). Instead of labels, I would use UITextViews. They fit large amounts of text by allowing the user to scroll. To make them hidden, use change the hidden selector attribute of the UITextViews. Because the UITextViews will never change in size, you can easily calculate how much to decrease the height of the UIView container by per UITextView. Hope this helps!
I think you have to calculate the height of the labels (more specifically, the addition from the original height) one by one. Of course you should be able to do this systematically by having all the labels in an array.
You can use [NSString sizeWithFont:] methods (there are several with similar names) to calculate the height.
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/NSString_UIKit_Additions/Reference/Reference.html
If you want to keep the same font size then you can calculate the frame size for the label at run time depending upon the length of the text..
See here
You need to used following two properties of label-
lineBreakMode
numberOfLine
when you use both of these properties then you will achieve what you want.
I have a UITableViewCell with two subviews, a UILabel on the left, and a random input control on the right. The random input control on the right can vary in size, as can the length of the text, but since I can set the word wrap of the text on the left, I need to be able to adjust the size of the UILabel based on the width of the random input control. To complicate matters, the app needs to work in both portrait and landscape modes, which give the table cells different widths.
This wouldn't be difficult if I could read the width of the table cells and set the widths of its subviews appropriately, but at creation time the width of the cell is 0.
Any ideas?
Nothing easier than that: every UITableViewCell is also a UIView, which has a method designed for just that: layoutSubviews, which is called whenever the view (here: cell) needs a re-layout. This is where you lay out the content.
I came across issue where I need to animate height change of UILabel frame or its enclosing view's frame. Label is multiline.
The issue is that given with large text which does not fit initially into label(say it takes 3 lines), then animating the label's height to increase, immediately changing 3 line to 4 and then animating the frame increase.
Opposite effect is when the text fully fit into label(4 lines), then I animate height decrease, 4 lines are instantly becoming 3 and only then I see animating frame size decrease.
This is of course not good for an eye.
What I expect is something like keep the label's origin.y intact and then as frame is increasing the more text is revealing from the bottom. The ellipsis may convert to missing word instantly, that is not a problem.
If you want to keep origin.y intact then you have to animate it with CoreAnimation stuff.
Set once:
label.layer.anchorPoint = CGPointMake(0,0); //I believe 0,0 is the upper left or it was 0,1?
after doing this you just need to change the size accordinly:
I would measure the text first (With NSString's methods)and see if the label needs to be resized.
In case it needs to then adjust label.numberOfLines and label.layer.bounds = CGRectMake(label.layer.bounds.origin.x,label.layer.bounds.origin.y,
label.layer.size.width, newHeight);
This should work
I hope this helps.