Dynamic table view height - ios

The idea is to resize height of the cell automatically based on few controls heights. As you can see on image above I have Top Label and Bottom Label. These two labels can have different height based on text length.
Few words about setup in storyboard.
I set number of lines to 0 for 2 described labels to allow grow their height dynamically based on given text.
For the Top Label I have next constraints:
For the Bottom Label I have next constraints:
So I we say about vertical spacing between 1000 green label and bottom label it's every time the same:
But without this spacing cell won't stretch height. How can I reduce this vertical spacing? Because there is to much spacing between "1000 green label" and bottom label in case if top label have big height because of text.
In -viewDidLoad method I set:
[self.theTableView setEstimatedRowHeight:145];
[self.theTableView setRowHeight:UITableViewAutomaticDimension];
Seems it works pretty cool sometimes with a bug described here but I don't know how to restrict that vertical spacing:
http://www.appcoda.com/self-sizing-cells/

Set the bottom label's top constraint to be >= 11.5 (or whatever its minimum spacing should be).
This will let the cell adjust that vertical spacing, depending on the other content in the cell.
Update:
In iOS 9, this would much more simply be handled by UIStackView.
A horizontal stack view would constrain (and determine the cell height based on the) two inner vertical stack views. The left vertical stack would handle the image, banner, and label layout, and the right vertical stack would handle the top label, 10000, and bottom label layout. You'd only need with 4 constraints (for the horizontal stackView to constrain it to the contentView).

Related

How to use auto layout so that the following layout is achieved?

I have a vertical UIStackView whose top, leading and trailing edges are pinned to the superview and whose height is determined by its subviews.
Its arranged subviews consist of 5 horizontal UIStackViews each of which have 3 UILabels as their arranged subviews.
For each of the horizontal UIStackView, the text of the first UILabel is the heading, the text of the second UILabel is the colon and the text of the third UILabel is the info as shown in the following image
All of the UILabels have numberOfLines = 0 so that they are multiline.
I would like to create constraints using auto layout so that the following conditions are met-
The colon UILabels are all vertically aligned
The width of the info UILabels are at least 20% of parent view
The width of the info UILabels are at most 60% of parent view
If the width of all the info UILabels is less than 60% of parent view ( see 3 ), then it must shrink to the width of the widest info UILabel.
I understand how to use auto layout to create constraints to satisfy the first 3 conditions.
However, I do not understand how to create constraint to satisfy the 4th condition. I tried increasing the "Content Hugging Priority" but it shrinks the label to 20% of the parent view ( see 2 ).
Can anyone point out how to achieve this layout?
This is considerably more complex than it would appear on the surface.
The "Info" column has to be evaluated for min/max width and word-wrapping, and the "Heading" column has to be evaluated for word-wrapping based on the "Info" columns variable width... and the "Info" labels have to match widths based on the widest wrapped (or not) text.
That's a lot for auto-layout to handle.
I don't think it can be done with constraints only. The main problem being that auto-layout calculates the height of the height of the Heading labels based on the potential for the Info labels to be at their widest.
So, we can end up with this:
and the Heading label text is no longer vertically aligned to the top of the label.
The best I could come up with is to override viewDidLayoutSubviews(), using a counter which forces auto-layout to calculate the Info labels first and then the Heading labels.
As to constraint settings...
The Heading labels need nothing special - just set the number of lines to Zero to allow word-wrapping.
The "Colon" labels don't need constraints, but they do need both Horizontal Content Hugging and Compression Resistance set to 1000 (required), because we don't want them stretching or getting squeezed.
The Info labels need:
Horizontal Content Compression Resistance: 1000
Horizontal Content Hugging: 999
Width: >= its stackView Width with Multiplier 0.2
Width: <= its stackView Width with Multiplier 0.6
Width: = its stackView Width with Multiplier 0.2 and Priority: 999
and finally, the bottom 4 Info labels need Width constraint equal to the top Info label.
The horizontal stack views that make up the 5 "rows" should be set to:
Alignment: Top
Distribution: Fill
Spacing: 8 (horizontal spacing between the "columns")
The vertical stack view that holds the 5 "rows" should be set to:
Alignment: Fill
Distribution: Fill
Spacing: 10 (vertical spacing between the "rows")
I've put up a project on GitHub that demonstrates the layout -- it has 10 different "variations" of label content to show how the sizing works: https://github.com/DonMag/MutlilineVarWidthLabelColumns
you can achieve this kind of UI by using min and max constraints.
you can follow the below constraints for it.
give max width to Heading label with the relation of the screen.
give fix width to colon label
Give leading, trailing, top, bottom to info label
change Horizontal content hugging priority of info Label to 252.
please check the below images for more details.
The actual structure of my example
Constraints for Heading label
Constraints for info-label
output
If you need any help then feel free to ask again.

Image getting resized after download in tableview cell

I am getting an image from a URL in a tableview cell. The image view is hugging the right top and bottom of a cell in the tableview cell. To the left of the image is text. I want the text to set the height of the tableview cell automatically and I want the image to conform to the size that is set by the text. How would I do that? Right now it is working but when the image is being downloaded, the cell resizes to become much larger because it uses the large dimensions of the image. As a result the cell in the tableview gets really tall. How would I fix this?
I know the issue is because I am using a greater than or equal to constraint between two of my labels as you can see below in the screenshot. But I need that greater than or equal to constraint.
Here is what my constraints look like:
This is what they look like and what I want it to look like:
This seems to be a cell that is laid out more or less as you desire:
The first label has three lines. The second label has four lines. The third label has one line. The first label has a leading constraint and a trailing constraint to the cell content view; the other two labels have their leading and trailing edges aligned to it. There are four constraints from top to bottom, content view to first label to second label to third label to content view.
The image view has its top aligned to the first label top, its bottom aligned to the third label bottom, its leading edge constrained to the first label trailing edge, and its trailing edge constrained to the content view.
That's all.
EDIT Sorry, I omitted a piece of the puzzle. For your use case, the image view's vertical content compression resistance would need to be lower than any label's vertical hugging priority. That says: "Let the labels dictate how tall I can be." Your labels have a vertical hugging priority of 251, so 250 would do.
You have set your constraints for the 3 labels, now for the image view set equal height to your cell(90-95% should do it). So the labels control the height of the cell and then the cell controls the height of the image view.
Edit: I think that you are complicating things. All your cells will have the same height(title,preview, source of 3,4,1 lines respectively), let them set the height, you don't need content hugging priority with the way i am suggesting.
I would use equal widths to set the width for all the items in your cell, the i would set the horizontal centers, for the spacing between constraints you can either use top-bottom constraints or set vertical centers and you are done.
Bare in mind that top-bottom-trailing-leading are NOT always the best choice, sometimes (like this one) can cause headache.

iOS How to fix UIButton height in a custom UITableView cell

I have a custom table view cell with two buttons. The accompanying text has a varying number of lines which affects the height of the cell. This height variations causes the height of the buttons vary. I have tried a lot different things to fix this with no luck. Currently the two buttons are in a stack view and that is in another stack view with the UILabel. I'd like the buttons with a fixed height vertically centered in the cell. What's the best way to do that?
Use only one stack view - for the buttons.
Constrain your UIStackView to the trailing edge of the cell's content view, and constrain it centered Vertically.
Constrain your UILabel to the leading edge of the cell's content view, and constrain it centered Vertically.
Also constrain your UILabel horizontal-spacing to the UIStackView, and edit it to be >= 8.
And, the key part, also constrain your UILabel Top and Bottom to >= 4.
Now, when your label wraps to multiple rows, it will "push the top and bottom", and your stack view holding your buttons will remain vertically centered, but will not "grow in height".

Autolayout Issue with Multiple Button Aligned Horizontally & Vertically with a Label

Please look at the ScreenShot attached for wCompact|hRegular for different screens, I am trying to make it working since hours but not getting any success. My requirement is that at the top there would be a label with some predefined margin. Although the Label content would render at the runtime, but I know the content size, so resizable label isn't needed actually I think. Now there would be three row at equal distance. In first and third row, there would be two buttons with equal height and width and in second row there would be button aligned horizontally. I have set the buttons image and text in storyboard. Control Alignment are set to Horizontal | vertical. Constraints for label are:
Pinned top space to superview, leading and trailing space equals to:8(superview), height equals:90.
Constraints for Button(View Transactions) are:
top space to label, bottom space equals to:8(New Launches Button) leading and trailing space equals to:8(superview) and 8(Place Request Button) respectively, and equal width and height for all buttons.
Looks fine for 4.7 and 5.5 But not satisfied with the output for smaller screens. As u can see resizing of buttons image not working properly(Larger space between button's image and text). One more thing is I don't wanna set the height of the label, cause it seems like a wrong practice in AutoLayout. Any help would be much appreciated.
You should set the Aspect Ratio for the Buttons, not just the equal width and height. In that case auto layout wont shrink the images.
Really you should put this into a scroll view so that if the height is too great the user can still see everything by scrolling. You should also not set static heights on labels, you should allow the intrinsic content size to apply.
Add a subview to your new scroll view. Pin the width of this subview to the width of the scroll view. Do not pin the height.
Add all of your buttons and labels to this new subview. Pin them to the edges of the view and allow the intrinsic content sizes to apply limits. Set various items to have equal widths and heights. Do not set explicit heights or widths (do everything by proportion or equality so auto layout can choose good sizes).

How to simulate conditional hugging priorities in AutoLayout?

I have a UIView that contains a multiline UILabel and a UIImageView. The imageView is a square that is a specific height and width and is centered vertically in the cell, while the label is constrained to the top of the view. Here's a little illustration:
I want to be able to make the parent view expandable based on either the UILabel or the UIImageView, based on which one has the bigger height. How would I go about doing this (in Storyboard)?
You would set a bottom and top constraint for both the label and image view at a high priority. Set the constant equal to the amount of padding you'd want.
Then, on the parent view, you'll want to add a height constraint with a lower priority than the top/bottom constraints of the label and image.
That way, you guarantee padding between the label/image and their superview, which will force the superview to expand its height since its priority is lower than that of the padding.

Resources