Prevent a UILabel from truncating tail - ios

I have two UILabels: name and description. The constraints are setup as the following:
name has left and top constraint
description has a right and top constraint
A minimum 10 pixels spacing constraint between them so that they don't overlap
When I run the program, not consistently, sometimes name is truncated and sometimes description is truncated.
Question is: Is there a way to guarantee that when running out of space alway truncate the right label?

The proper way to address this is to change the Content Hugging Priority for one of the labels. By default, this is set to 251. Just change one of the label's Content Hugging Priority to 250 or 252 depending on how you want it to be "hugged".
In code:
func setContentHuggingPriority(_ priority: UILayoutPriority,
for axis: NSLayoutConstraint.Axis)
Or interface builder:
And check out this post if you need more info about this topic: https://medium.com/#abhimuralidharan/ios-content-hugging-and-content-compression-resistance-priorities-476fb5828ef

You could try setting a minimum width constraint for the left hand label (lbl1) then connecting the constraint to an IBOutlet in your ViewController.
Then on load or willAppear or any other related action, determine the minimum width of lbl1 and set that to the constraints constant.
Then before the view appears, it should update the right hand label to the correct width without truncating the label on the left.
For reference of determining label size see this answer:
https://stackoverflow.com/a/19128912/933887

You can use this property in reducing font size is not the iss

You may use UILabel().adjustsFontSizeToFitWidth = true if you are okay with smaller font.

Related

UILabel height depending on font size

I am using a UILabel in a UITableViewCell to display a title. Normally the text is not too long and therefore the font size can be large. Notice how the text fills the height of theUILabel like normal.
However, when there is a larger title, I want the UILabel height to reduce to accommodate the smaller font size and not leave a blank gap in its place. Currently, my configuration produces this effect.
I am using constraints in my storyboard and have deliberately not set a fixed height constraint. Here are the relevant constraints added:
I may have made a rookie error in my configuration as I can't remember this effect happening before, but it is giving me real headaches (and a bad looking UI).
When UILabel is set to auto-adjust font size to fit, it does NOT auto-adjust the height of itself.
You have a couple options:
set Baseline to Align Centers, and just accept that you will have top and bottom padding
use code to calculate the "scaled font size" and update the font size of the label
Remove either the Top Space or Bottom Space constraints (depending on where you want the label to be anchored).
This will cause the label to automatically use fit itself to the text size.
Try this and see, it should work according to your need:
Set Top and Bottom constraints attribute Greater Than or Equal To and add horizontal center (Alight Center Y to superview) and show in this image.

iOS AutoLayout - Label overlaps nearby label

I have a problem with a label constraint.
My goal is to have 2 labels on the same Y coordinate of a tableViewCell. One of the labels is pinned on the left side and the other is pinned on the right side.
Like that:
[This is the first label] [Second]
The first label should have a dynamic width based on the text which it has to display, BUT it should end about 20 points to the second label.
I tried that with numerous constraints, but sometimes the first label seem to push the second label out of the view and sometimes the first label just overlaps the second label like in this example:
The first label has constraints for:
Top Space to Superview
Leading Space to Superview
Bottom Space to a third label
Trailing Space to THE second Label (<= 20)
What is the correct way to display the two labels correctly?
Thanks in advance, appreciate your help!
EDIT
Tried the solution with giving the second label a maxwidth. Now, it is randomly working or not working. I don't get this at all.
Like others have said, you need to set the trailing constraint from the left label to the right label as greater than or equal to, so that there is a gap of at least 20 between the two.
But, you also need to designate which label truncates first. By not doing this, iOS will take it upon itself to choose, which is probably why your current solution works only some of the time. This is where Content Compression Resistance Priority comes into play. Set the value lower for the label you want to truncate first.
You can do this on your storyboard under the size inspector.
I'm assuming you want your left label to truncate first. In that case, make sure the left label has a lower horizontal content compression resistance priority than the right label. Notice how above I just dropped it to 749, as the default is 750.
Check out this answer for a good explantation on content compression and content hugging.
if your second label on the right side has fixed width or max width :) here is what you can do :)
Set the distance between left label and right label to >= 20
set the width of the right label with some value using [yourvalue] or [>=your value]
SO overall here is how label's constraints should appear
|-(distance_to_left_Label)-[left-label]-(>=20)-[right_lable(your_value)]-(distance_to_right)-|
Hope my answer helped :)

iOS autolayout disregarding "trailing space" constraint, using width/content size instead?

I have a UILabel (the subtitle) that I want to have a static X origin, but extend to the edge of its nearest neighbor. There's a button ("Visit Link") that is optionally removed from the superview at runtime if not needed. The constraint from the label to the button has a priority of 1000, and the constraint from the label to the superview container has a priority of 250:
However, when I run the application removing the button (via .removeFromSuperview() in the viewDidLoad method), via the view debugging I see that the content size is setting the width of the label, taking priority over the constraint I have set.
I expect the label to extend to the edge of the view, but as you can see, the constraint is greyed out - I assume trumped by the (content size) constraint instead:
Does the (content size) constraint have a higher priority than my Trailing Space to: Superview constraint? And how can I change it, since it's not a constraint I've even defined?
When you remove the button from the view hierarchy, that also removes any constraints involving the button. So, all that's left is the trailing constraint to the superview at priority 250.
The label has an intrinsic width based on its content. That means that its horizontal content hugging and compression resistance priorities come into play. Its content hugging priority is 251.
That means that it's more important to the auto layout system that the view's width be no larger than necessary than it is to keep its trailing edge at 8 points from the superview's trailing edge.
You should probably increase the priority of the trailing constraint. You want it to be less than the trailing constraint to the button so that, in the case where the button is present, it doesn't conflict. You also want it less than the button's compression resistance priority, so that the button doesn't get squished to allow the label to be 8 points from the superview. But, other than that, you want it to be as high as possible. (In the hypothetical case where you simply got rid of the possibility of there being a button, you would normally make that trailing constraint required, right? So, it should be as close as possible to required without causing undesirable side effects.)
If you're targeting deployment to iOS 9.0 or later, you should consider using a UIStackView for this layout. It will take care of some things for you, like adding or removing the appropriate constraints when the button is hidden or shown.
The (content size) constraint, automatically installed by the system at runtime, seems to have a priority somewhere between 250 and 750. When I use 250 or 251 for my Trailing Space constraint, it does not work.
However, bumping the priority of my Trailing Space constraint up to the Xcode-titled High priority of 750, allows it to take precedence. So the defaults for the width of UILabel seem to fall "somewhere in the middle."
Autolayout, you silly.
From the second screenshot, it looks like everything is working as it is supposed to.
Two things I'd like to mention:
Always try to set up your layout so you have as few constraints as possible. Each constraint adds complexity.
Yes, content size of the label does indeed have a higher priority. That's why the label is not resized to the right-most edge, which is good. What you are seeing is the label's intrinsic size which means that UIKit knows how big the label is supposed to be drawn, depending on font, text, etc.
To make this layout a bit more robust, I'd change the Trailing space of the label so that it has priority 1000 but is >= 0.
This way, the layout will be valid with or without the Visit Link button and the content size of the label (it's intrinsic size) will resize it to whatever length it needs to be, but no more than the right edge of its superview.
Hope this helps!
UPDATE: Wrote a quick post on why this content size is appearing and why you should use it to your advantage.

Equal width and equal spacing between buttons in autolayout

I'm trying to use autolayout constraints to automatically resize a few similarly-sized buttons in a view to give the following effect:
Before resizing
Desired effect after resizing
As you can tell, I want the buttons to be of the same size and I also want the spacing between each button to be a constant 20 points. It seems pretty simple at first, so I set the following constraints:
Buttons: space from left neighbour = 20 (inclusive of left-most and right-most buttons)
Buttons: space from right neighbour = 20 (inclusive of left-most and right-most buttons)
Buttons: same width
What actually happens after resizing
When in preview or when I test run the app in my iPhone/simulator, the button resizes and doesn't even follow the same width constraint I set for it. In fact, the view containing the views also resizes to fit the new button sizes. Anyone knows how to fix this problem purely in the interface builder?
Setting:
- equal widths of all buttons
- horizontal spacing between all buttons
- leading to superview for the first button and trailing to superview for the last button
should do the job. Unless you're having problems with the superview (e.g. ScrollView missing constraints)
In the interface builder you set the spacing constraints between buttons like you described above. Then you can command-select all of them and specify the "Equal Width" constraint to apply to the selected objects.
Finally I have oblivion how to solve this problem. I've test it works like charm.
add constraints to space items with 20 units margin
add constraint to ages
now tricky part
for each item add constraint equal widths to a parent
select all this new constraints and change its properties
set multiplier to value 1:5
set constant to -24 (6 separation between items and parent edge gives 120, this multiplied by multiplier value 1:5 gives 24)
update items frames
That's it! Picture below show how it works in interface builder:
Set simulated size to "freeform" and test different widths (I sett this to 330).
This problem is seems to be because of wrong content hugging priority and content compression Resistance priority. So you should set them as low content hugging and high compression resistance (all should have same value).
Because content hugging is the property that resist a view to grow and content compression Resistance priority is to resist a view to shrink. For more information regarding these you can found this Question.

Allow UILabel to grow dynamically using auto layout

I have a label which is going to contain a big description. I want the label to continue growing on new lines. In the image, its the label which starts with event_venue.....
The even_venue.. label has 3 constraints for now:
Vertical space with eventt_title
a horizantal space with the leading of the superview
a width constraints which defines that the label width is always less than the superview.width.
What I want to acheive is to make the event_venue.width less than superview.width, but if it has more text, it should display in new lines. Is this possible using autolayout?
This are possible steps which can create expandable UILabel
Set layouts for UILabel fixing its position
Set number of lines = 0
Set content vertical compression resistance to 1000 (this will allow text to push the label)
Since you want UILabel to expand you cannot give it fixed height constraint or its parent fixed height constraint. Sometimes depending upon condition giving height constraint is necessary to avoid error then you need to set its priority lower than vertical compression resistance
Yes, this totally is possible. I see answers here that are close to solution but not complete. Here is a solution which works with auto layout in Storyboard, no coding of sizeToFit or anything. Your modified steps would be:
Vertical space with eventt_title
A horizontal space with the leading of the superview
A horizontal space with the trailing of the superview
Set UILabel's Line Breaks as Word Wrap.
Set UILabel's lines property as 0.
I have solved a similar problem. I had to make a label that had a variable amount of text. Here's what I did:
In the storyboard, place your label with the origin where you want it.
In the Attributes Inspector, "Label" section, set the Line Breaks = Word Wrap
Fill the label with random placeholder text to the maximum shape you want. For example, if you wanted to fill the whole width and have room for a maximum of three lines of text, you could do:
abcdefghijklmnopqrstu
abcdefghijklmnopqrstu
abcdefghijklmnopqrstu
In the code, set the text of the label using setText:
[self.myLabel setText:#"MyLabelText"];
This did it for me. Your situation may be a little different in that I wasn't changing the width of the superview and it sounds like you might be. But if the width constraint is set on the label then I would expect this to work in your case, too.
I had a similar question about label resizing, and the answer that I found that was useful to me is here: UILabel Auto Size Label to Fit Text. This is a good starting source for code on how to resize your label programmatically.
I would recommend that you also add a horizontal trailing auto layout constraint from the label to the edge of the superview. Do that and you can then get rid of your current width constraint.
AutoLayout facilitate you for orientation purpose. I don think it will give you automatic expansion. You have to define label with width and height completely, otherwise you will see dots at the end of label. So you may use UITextView expanding it all over the screen. And set textView.backgroundcolot = clearColor.

Resources