0

What is the proper way to make a fluid layout in iOS, in the sense that hidden elements do not take up space anymore?

I have a table view with in each cell a customized detail-type of view with title, subtitle and a row with some extra information:

Picture of situation with no hiding logic in place

The extra information can be up to three pairs of an icon and a label with a value. The layout of all views inside the cell is done using AutoLayout with no missing or ambiguous constraints.

What I would like to achieve is that when the value is 0, the icon and the label are not displayed and the views on the right are shifted to the left.

If I just use the setHidden: method, the width of the hidden parts are not changed, so that there is just whitespace, but no views are moved. Example:

Picture of current situation with undesired whitespace

It should look like this:

enter image description here

The following questions are related but do not seem to fit my case:

I have tried to follow the approach with creating layout constraints for the four frames that need to be set to zero: the width of the heart-shaped icon, the width of the label containing the value, the whitespace in between those and the whitespace between the label and the next icon. This did not work because I could not bind the layout constraints to the outlet in the code, and besides it seems a cumbersome method for something that should be a common scenario.

EDIT: I fixed the problem with the outlets to constraints: to do this it is necessary to create a subclass for the table cell and creating outlets for the constraints there.

With "common scenario" I refer to doing something similar in web design, where setting the display style to none is simple and has the desired effect. I expect that there is something similarly simple for this in iOS.

I have been thinking of using a collection view with reusable cells, but then I need to set up a delegate and a datasource and everything, and before I would go this way I wanted to make sure that that is the way to do it.

Community
  • 1
  • 1
Martijn de Milliano
  • 3,908
  • 3
  • 36
  • 45
  • 1
    [This answer](http://stackoverflow.com/questions/18065938/how-to-use-auto-layout-to-move-other-views-when-a-view-is-hidden) should help you out. – bbarnhart Feb 17 '14 at 21:34

2 Answers2

4

There is no need to remove a hidden view. Connect the constraint to an outlet in the code, and when you determine a view is hidden, subtract from the constraint's constant. Then, in the cell's prepareForReuse, remember to return the constraint's constant to the correct value.

Léo Natan
  • 56,823
  • 9
  • 150
  • 195
  • When you say "No need" does this mean that it works anyway but is expensive, or will removing the view cause problems in case this cell is reused and the view should be shown again? So far it seems to work, but maybe no reuse has yet taken place? – Martijn de Milliano Feb 21 '14 at 00:22
  • @MartijndeMilliano If you attempt reuse and need to display the view, shit will hit the fan. You have to add it back to the hierarchy and set up the constraints again in code. This is terrible. Compare with a simple constraint value change and then reset. And on top of that, removing and adding constraints is slow, much slower than updating an existing constraint. – Léo Natan Feb 21 '14 at 00:32
  • 1
    I am now convinced this is the best answer, I updated my code to do this. Still a bit cumbersome to have to subclass the cell to be able to modify the constraints, and to have to modify four constraints (in my case) to pull off something that was supposed to be simple, but there's probably a good reason... – Martijn de Milliano Feb 23 '14 at 00:58
2

Hidden views maintain their frame, so auto layout will have no reason to adjust the view. The correct way to do this would be to remove the views from the superview. The last thing you must do is double check the constraints. Since you will be removing views, you cannot use those views for auto layout. This will require quite a bit of constraint setting on your UI.

willhblackburn
  • 291
  • 3
  • 12
  • This is a very heavy and unnecessary operation. Adding constraints at runtime is heavy and performance will suffer when scrolling. – Léo Natan Feb 17 '14 at 21:51
  • Thank you for your explanation; that is indeed almost the solution. The link indicated by @bbamhart contains the crucial missing step (at least for me): over-constraining the layout and setting priorities correctly. I am not sure whether this was what you meant by your "double check the constraints", but in any case I have clarified this in your answer, with your permission, and accepted it. – Martijn de Milliano Feb 21 '14 at 00:10
  • I did some more research and the answer by @LeoNatan seems the correct solution. – Martijn de Milliano Feb 23 '14 at 00:59