UILabel not recognizing a horizontal space constraint - ios

I have a simple UIScrollView that I'm adding subviews to. The problem is that I have 2 identical UILabels with symmetrical constraints, yet the UILabel on the right is not stretching to the edge of the superview (the red indicates where I want it to be, equal to the width in front of the left label) and instead seems to be resizing to only fit the width of the text all while following the other constraints placed on it properly.
Below are the associated constraints for the 3 subviews in the first screenshot. As you can see, the constraints are the same for each UILabel only flipped. It's the right label's "Trailing Space to: Superview (Equals 15)" that isn't being recognized.
Other relevant information that might be applicable are as follows:
My UIScrollView is pinned to the superview with trailing space and
leading space equal to 0. Here is the view hierarchy:
The left UILabel contains the static text "Request" but the right label's text is generated dynamically via the view controller.
I have IBOutlets for both labels. The only code I use on the outlets is this:
// Left UILabel
requestLabel.layer.cornerRadius = 10
requestLabel.clipsToBounds = true
// Right UILabel
swapTypeLabel.layer.cornerRadius = 10
swapTypeLabel.clipsToBounds = true
I'm no expert in auto-layout but would someone be able to tell me what is preventing the right UILabel from following the Trailing Space to Superview constraint and instead resizing to fit the text, and how I can go about fixing it? Thank you.

Related

Setting the constraints of a UI Collection View Cell

In my UI there is a collection View where each cell contains a UILabel and a UIImageView. There are aligned as follows.
Where I am stuck is setting constraints to them because each UILabel has a random length. I always want to make the distance between left side of the image and left side of the cell equal to the distance between the right side of the label and the right side of the cell (in a certain cell).
I know I can set the centerY of each element equals to centerY of each element. But how can I set the other anchor.
I am not Using Storyboards.
I would add a horizontal stack view, set constraints to every edge with the desired margin, and add the image and label to the stack view.
Then set the hugging priority to the image view higher than the label. This will cause the label to take up the remaining space while being aligned to the left.
If I understand your problem correctly, you want to set spacing for left side of UImageView and right side of UILabel equally. For this, I would recommend you to put those views (UIImageView and UILabel) in a UIStackView with properties: axis as "Horizontal" and Alignment as "Center"; and adding constraint for Leading and Trailing Space with CenterX and CenterY Constraint.
For ease of understanding take a look at the image of UIStackView Constraints

How to horizontally align two UILabel (with fixed and variable width)

I have been facing issues horizontally aligning two UILabel and one UIImageView like this:
First label has variable width, can be truncated if long. Second label has fixed width, it should always be aligned to right of UIImageView. It should never go off screen. UIImageView is aligned to right of first label.
I have tried embedding them in horizontal UIStackView but the image + second label always aligns to end of cell. Got the same issue when trying without UIStackView.
Please help.
You can embed both label and horizontal StackView into another horizontal stack view. Then, you'd need to set the dynamic width Label's Content Compression Resistance Priority (you can find this property at the bottom of the Size Inspector), to be smaller in order for it to shrink.
Then on the container StackView (the one that contains all views), you'd need to set constrains to top, bottom, leading to 0 to the superview and the trailing to be greater than or equal to 0, for it to not take all space of the superview, but at the same time not get offset if the content is too wide.
I hope that is clear enough!

How do I make the UIView superview of a UILabel fit the intrinsic height of the UILabel using the storyboard only?

I got a UIView whose child is a UILabel. I then aligned the left, top, right, and bottom of the UILabel to that of its superview (the UIView) using constraints.
But what I'm getting is a UILabel that matches the height of its superview but not its intrinsic height (smaller or larger than its text content depending on the size of the UIView). What I expect is for the UIView to resize itself to fit exactly the height of the UILabel.
So how do I do this using only the interface builder?
In order to make the UILabel keep its size and force the outer view to resize you can update the values for Content Hugging Priority to 1000 (a.k.a. Required). This can be done in the measurements panel when selecting the label in Interface Builder.
I think they are set as a default to 750.
This should (if there is nothing else causing the change) make the label take its intrinsic content size and force its superview to conform to that size also.
Align top, trailing, bottom and leading of UILabel with UIView (add constraints).
Remove height and bottom constraints from UIView if any.
If the content is large, you probably need to wrap UILabel into a UIScrollView in place of UIView. and add a bottom constraint to UIScrollView
Content Hugging Priority of UILabel (251) is more than that of UIView (250) by default. Verify this
It's super easy using auto-layout. Just, follow these steps
1 - Drag a UIView and align it vertically and horizontallyin centre.
2 - Now drag UILabel into the UIView and align the label also horizontally and vertically in centre.Now, the IB aligns the label at the centre WRT to the superview and not the UIView.So, change that in the size-inspector section.
3 - Once you have done that and all red lines are removed, select both the label and the UIView together using the command key.
4 - Now, give them constraints as follows
leading = 0, trailing = 0 and select the equal width and equal height.
There you are done.If you wanna test that the UIView size is respective to the label's content, try increasing the label's font to a bigger size and you will see that the size of the view will be the same as the size of the label.
There , you are done :-D. Hope, this was helpful.
If someone is experiencing this issue, while:
Having 2 labels inside the UIView
Doing everything what was suggested here
In my case, I set Vertical Content Hugging Priority of BOTH UILabels to 1000. Then one of the labels had a different font. (ie. one label was supposed to be smaller than the other one)
The height was being ambiguous, because both labels were trying to force their height on the superview. Once I lowered the priority on the smaller label, everything worked fine.

Limit the height of a UILabel inside a UIScrollView

I have a UILabel inside a UIScrollView and the contentSize of the UIScrollView is determined by the amount of text in the UILabel. I have managed to define a minimum height for the contentView inside the UIScrollView by making the height, width and aspect ratio constraints optional.
This is how the hierarchy of the UIScrollView looks like -
UIScrollView
contentView
UILabel
In some cases, even when the text is huge and makes the label expand beyond it's frame, I wish to have the frame of the UILabel stick to it's square frame with the extra text getting truncated. I am using autolayout so I believe this won't be possible by merely setting the frame of the UILabel and it has something to do with changing the priorities of the constraints.
Constraints for the UILabel -
The UILabel has its leading, trailing, top and bottom connected to the contentView.
Constraints for the UISCrollView-
Required
Trailing, Leading, Top and Bottom to the superview i.e. the UIScrollView
Optional
Equal height and width to the superview (UIScrollView) and aspect ratio = 1:1
EDIT
And I need to do it in a way that when I set the lineBreakMode of the UILabel to NSLineBreakByTruncatingTail, the text automatically gets truncated and textLabel.text only returns the visible text.
Ok, so if I understand everything correctly, you want to have an expandable label that either shows its entire text, or has a square form. This should as easy as enabling/disabling a constraint such that label.height <= label.width (or ==, depending on what you want it to look like if there is less text then would fit a square label). You can create this constraint in interface builder, add an outlet for it and then simply do:
self.labelSquareConstraint.active = YES/NO;
As to the question in your edit : there is no easy way to get the visible part of the text from a label, but there are some threads on SO about this, for example :
Get truncated text from UILabel
UILabel visible part of text
Calculate the range of visible text in UILabel

Auto resize UIView based on multi line UILabel

Problem:
I have a custom view with a multi-line UILabel (se picture below).
This custom view is then added to a screen in my storyboard (se picture below).
This works great. The problem is that the multi-line label will change dynamically a few times under execution, and then the blue UIView box won't fit. It's also a problem with smaller/bigger screen size.
Question: So how do I get the UIView to automatically resize in height according to the height of the UILabel? Is it possible to do through Interface Builder and Autolayout? (not nececery, but most of my other settings are done through IB)
Let me know if there is more details needed.
As long as you make sure that labels in your custom view are pinned to all sides (Title Label pinned to: Leading, Top, Trailing of the superview and Bottom to Content Label; Content Label pinned to: Leading, Bottom, Trailing of the superview and Top to Title Label) you will have your superview change it's height according to the content.
Also, note that your superview won't need a height constraint, just pinning it to the Leading, Bottom and Trailing sides should be sufficient.
I had almost identical view in one of my apps. What I would do to make sure the height changes according to update is this:
customView.setNeedsLayout()
customView.layoutIfNeeded()
You can also wrap this code in UIView.animate(withDuration: ...) block
Cheers!

Resources