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.
Related
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:
I have two labels side by side. And I have two constraints set. Label-A starts at the leading edge of the view. Label-B starts 10px from trailing edge of Label-1. There are no width constraints.
Label-A's text length varies; Label-B's text is fixed (6 chars long). This works fine until length of Label-A goes over a certain point. Then Label-B goes off screen.
Before I assign the text value to Label-A, I want to truncate Label-A text with '...' if it will push Label-B beyond the trailing edge of the view. Any idea how to figure out if I should truncate Label-A's text and by how much? This has to work in both portrait and landscape modes.
Thanks.
Set Content Compression Resistance Priority for one of both label, according to your requirement.
Look at these snapshots:
Two labels with default content compression resistance priority.
I changed content compression resistance priority for label blablabla blablabla, from 750 to 749.
Result is:
For more details see Apple document: Setting Content-Hugging and Compression-Resistance Priorities
Make the horizontal content hugging priority and horizontal content compression resistance priority of Label-B higher than Label-A. And also add trailing of Label-B to superview.
First of all make sure that your labels have constraints for leading and trailing.
Your views layout should like this:
|-8-[Label-A]-10-[Label-B]-8-|
After that set the horizontal content hugging priority and the horizontal compression resistance of Label-B higher than Label-A.
In my storyboard, my view controller has two container views as shown below
The second container view is it tone am having difficulty setting constraints for.
When I actually run the app, the text field, becomes very narrow. My horizontal constraints are obviously incorrect but I can't figure out the right settings.
Here what I currently have:
FilterIcon - trailing space to superview (right): 0
- Align Center Y
- Leading space to "Go": 16
- Equal height to text box
Go Button - align center Y
- trailing space to filter icon: 16
- leading space to text box: 8
Text Box - leading space to superview (left): 0
- trailing space to Go Button: 8
- equal height to Filter icon
- horizontal hugging priority: highest of 3 elements 751
I thought the text box would expand from the left margin until it reached the Go box which is set to the right based on the filter icon.
Instead I get this result:
What am I missing for the constraints?
How about configuring like this?
Text Box
leading space to superview (left): 0
trailing space to Go Button: 8
equal height to Filter icon
horizontal compression priority: 752
Go Button
align center Y
trailing space to filter icon: 16
leading space to text box: 8
horizontal hugging priority: 251
Filter Icon
horizontal hugging priority: 251
Align Center Y
Leading space to "Go": 16
Equal height to text box
Here is my screenshot.
If you don't want to set priorities, you can just set width constraints for both Filter Icon and Go Button. For more information, there is very good tutorial about content hugging priority and compression resistance priority in here
I think you can set both buttons' height equal to width. Then other space is left to the text field.
Give aspect ratio to the text field for its width and height and give center y to superview. This will definitely work. But make sure when you give aspect ratio, your text field is having the width you require.
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....
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.