Horizontal UIStackView with two label (one multiline label, one one-line) - ios

I have a horizontal UIStackView which has two UILabel in it. First UILabel is multiline (two line) and other one is one line only. They both have default content compression and resistance priorities. My problem is that even there is a gap between labels, "best" word in first text goes second line. I noticed that first label doesn't goes beyond half of total width.
What I want is that second label should always show itself and first label should size It self for remaining space. If It can't fit to one line It should be two line. However, If second label is too short and first label is a long one but both of them can fit, first label should go beyond half of the width.
P.S I need to use UIStackView in this scenario because there are other cases. I know putting two label inside UIView may solve the problem.
UIStackView:
- Distribution: Horizontal
- Alignment: Center
- Spacing: 0
UILabel:
- Number of line: 2
- Line break: Word wrap
UILabel:
- Number of line: 1
View hierarchy:
Desired Result:
OR
EDIT: I calculate the width of second label and give width constraint. I think It solved my problem, I'll test a bit.
//Give specific width to second label to make first one calculate right number of lines.
if let font = UIFont(name: "Metropolis-ExtraBold", size: 15) {
let fontAttributes = [NSAttributedString.Key.font: font]
let size = (secondLabelText as NSString).size(withAttributes: fontAttributes)
secondLabel.widthAnchor.constraint(equalToConstant: size.width).isActive = true
}

To try and simplify...
Forget calculating any widths... what matters is the horizontal Content Hugging and Content Compression Resistance
Leave the left (blue) label at the defaults:
Content Hugging Priority
Horizontal: 251
Content Compression Resistance Priority:
Horizontal: 750
But set the right (orange) label to:
Content Hugging Priority
Horizontal: 1000
Content Compression Resistance Priority:
Horizontal: 1000
Results:
The only other issue would be if the text in the right-side label exceeds the full width of the view -- but you haven't indicated that you might need that much text.

You should set different horizontal content compression resistants for each of them:
For this case, the blue one(multiline) should have something less than the orange one(Singleline).
Assistive note: Multiline: 250, Singleline: 750
Orange Settings:
Blue Settings:
Note that I have set the line limit of the orange one to 0. You can set it to anything you like. But if you like to make it selfsize to anyhight taller view should have higher vertical compression resistant than 250.

First embed your multiline label inside a view and constraint the label to this view (top, leading, trailing, bottom). After that add your view with your multiline label and single line label to your stackView.
Then you can use .fillProportionally for the distribution of your UIStackView and the spacing value to specify the space between your two labels.
Make also sure to use Required (1000) for your horizontal content compression resistance priority on your right number label.
View-hierarchy:
Result:
With spacing between your labels:

Related

Arranging two side-by-side items in a Table View cell

Each row in a table (UITableView) consists of two elements: label and value.
Value is right-aligned and is wide enough to hold the text without wrapping. Label is left aligned and takes all the width remaining after value (with a small margin). It allows text wrapping.
UIStackView (horizontal) appears to be the one, but I couldn't find a way to say: 'this takes as much as needed, and that takes all the rest'.
Is there a solution without coding ?
Update. After suggestion by Mr Bista, I've made the following:
StackView:
Alignment: Fill
Distribution: Fill
Content Mode: Scale to Fill
Constraints: leading: leadingMargin, trailing: trailingMargin
Label:
Alignment: Left,
Line Break: Word Wrap,
Lines: 0
Content Hugging Priority: 251 Both
Content Compression Resistance Priority 750 Both
Value:
Alignment: Right,
Line Break: Truncate Tail,
Lines: 1
Content Hugging Priority: 251 Both
Content Compression Resistance Priority
751 Horizontal, 750 Vertical
The fields are spaced equally both with distribution Fill or Fill Equally (top image). With "Fill Proportionally" I lose Value at all (bottom image). Maybe, I am missing something?
Set the Content Compression Resistance Priority of value label to 751 i.e 1 more than Label Label 750.
Also set the Alignment and Distribution of Stack View to Fill.

Autolayout constraints to set labels horizontally

I have a bar with two UILabels:
[LeftMsg RightMsg]
The rules I want to set are:
RightMsg is always fully visible, right-aligned and takes the room it needs.
LeftMsg is left-aligned and takes the remaining room.
For example, if LeftMsg reads "This very long message does not fit the bar", it must be displayed as follows:
[The very long message does n... RightMsg]
I set horizontal auto-layout constrants as follows:
LeftMsg.leading = Superview.leading
RightMsg.trailing = Superview.trailing
LeftMsg.trailing <= RightMsg.leading
(If I use equality in the last constraint, XCode tells that there is a content priority ambiguity).
Now it works as follows:
[The very long message does not fit the...]
that is not what I need.
Can anyone suggest how do I correctly set constraints to achieve what I need?
I think you can set lower horizontal hugging priority for your left label than that of right message label, while at the same time setting higher horizontal compression resistance priority for right message label than that of left message label.
For example, you can set both Content hugging priority and compression resistance priority for your labels like this.
Left Label : content Hugging priority ( H: 250, V: 251)
compression resistance priority ( H: 750, V: 750)
Right Label : content Hugging priority ( H: 251, V: 251)
compression resistance priority ( H: 751, V: 750)
You can see more information about content hugging and compression resistance in this tutorial.
Set the content Compression resistance property of the left label to 750.
Set the Content Hugging Priority of the right label to 250.
Please follow this,
First set both label on View.
Set constraints for View is Top, Bottom,left and Horizontal center
align.
Set constraints for left label is Top ,Bottom,Leading and
Trailing.
Set constraints for Right label is Top ,Bottom and Trailing.
Select both labels and set Equal height and Equal width.
Finished....

Content hugging with auto shrink

I have a UILabel with no of lines = 1 and auto shrink set to a minimum font size of 9. The font size of the label is system 70.0
I have increased the content hugging priority to 1000. I did this assuming that the height of the label will fit itself to the text.
But still the UILabel does not resize itself to fit it contents. The height of the label is very large. I want the height of the label to just fit it contents.
Thanks.
The problem is you have given both leading and trailing space, so label will stretch itself to satisfy these constraints, As label has intrinsic size(i.e it calculates size based on its content), you just need to give constraint for x and y position
So, delete your leading and trailing space constraint, just have Align CenterX and Align CenterY constraints, these will be sufficient to give x and y position of your label and you will get desired results.
Edit - Adding Screenshot.
Also understand that here I have given trailing space constraint >= 10 so that label can resize itself according to its content.
Also if your are checking in iphone 6 screen then AutoShrink Minimum Font Size - 9 will not be fit for screen width, try giving AutoShrink Minimum Font Size - 6.
Result of above constraint -
1.For Long text
For small text -

How fill a UITableViewCell with multiple UILabel using auto layout

i have a UITableViewCell that contains some UILabel and i want that this label fill horizontally the width of the UITableViewCell and that doesn't remains big space instead of other, this is an example:
|---------------------------------------------------------
| |
|***This is a uilabel***This is a uilabel***label***lb** |
| |
|---------------------------------------------------------
So with different UILabel width i want that all the UILabel fill all the UITableViewCell fixing the font size if needed, the * is the spacing, how i can achieve this with auto layout?
STEP 1: Set up constraints
Leftmost label: Add a leading edge constraint and a center Y constraint to its superview
Middle labels: Add a horizontal spacing and center Y constraint to previous label.
Rightmost label: Add a horizontal spacing and center Y constraint to previous label plus a trailing edge constraint to superview.
These constraints ensure the gaps between the labels and on the left and right are fixed in size, and that they are all centered in their superview. Because there are no width constraints, the layout system will attempt to size them to fit their content. But this leaves an ambiguity...
STEP 2: Set content size priorities.
The above constraints are still ambiguous -
If the total text content is less than the superview's width, which label will expand bigger than its content?
If the total text content is more than the superview's width, which label will contract shrinking its content to fit?
The answer to the first question is the label with the lowest horizontal content hugging priority. By default they will all have the same, so make sure they have different horizontal content hugging priorities.
The answer to the second question is the label with the lowest horizontal content compression resistance priority. By default they will all have the same, so make sure they have different horizontal content compression resistance priorities.
STEP 3: Ensure text shrinks to fit.
We now have an unambiguous layout. But by default, the labels will truncate their content if they do not have room to display it. Set Autoshrink to Minimum Font Scale or Minimum Font Size on your labels to ensure they adjust font size to fit their content rather than truncating it.

Text alignment from bottom to top iOS SDK

As seen on the screenshot above, each top cell has few labels. The frame of the label this question concerning is highlighted with green rectangle. It shows the title of some picture/sculpture or other exhibit, so there could be quite long strings.
I would like the text of this label to be just above author label (string with font of smaller size). So, normal text is aligned from top to bottom and if text is not enough to fill all the space, the gap is at the bottom part of the label.
For this label I would like to use the opposite approach: if text is not enough, all the text at the bottom. Is there any parameter of UILabel to implement above mentioned behaviour? Or I should manually count the amount of lines and adjust the size of the label?
This is fairly easy using constraints. To get the effect you desire:
Constrain your label's position above the author label
Constrain the label's width or horizontal position
Constrain the label to a reasonable height using a greater than or equal to
Either constrain the label's total height as less than or equal to, or constrain the vertical position to something greater than or equal to.
All these constraints can be added in IB very easily, or through code. These constraints will cause the label to grow vertically to accommodate more text, and then shrink back down with less text, which will achieve the effect of having the text grow up from the bottom.

Resources