This illustration shows what i'm trying to do:
The green list is the UITableView where it dynamically adjust it's height based on the number of items inside of it.
Underneath of the UITableView is a button that should follow the UITableView whenever it changes it's height size.
The UIButton should always be beneath the UITableView whatever the size of the UItableView.
I'm currently using autoresizing for UITableView
I have tried to use Autolayout but it seems i can't still find the answer.
i currently have no constraints in the layout.
This boils down to calculating the height of the table view that perfectly fits the cells. Basically you need to measure the size of every cell, then create a height constraint on the table view, and set its constant to the sum of the cells' heights.
Measuring the height of cells is tricky thought. If you only have a few cells (like in your illustrations), you can just instantiate all of them, keep them in an array and use systemLayoutSizeFittingSize to calculate their sizes. If you use multi-line labels, it is also important to set their preferredMaxLayoutWidth to appropriate values.
However, if you have only a few cells (and so cell reuse is not important), stack view is probably a better choice than table view. It's just too tricky to calculate the perfect height of a table view.
Related
I have a UICollectionView that is using flow layout and it is horizontally scrolling. In each cell, I have five subviews (labels and image views). I have an array of model objects, one object per cell, that contains the data to be displayed in each subview in each cell.
Some items can have more content than others (some labels will have more text), but I want all the cells to be the same height. I also want it so that the top of each subview is lined up with the tops of the same subview in the other cells. And if all model objects have a nil value for one of the fields, then the subviews for that field should be left out of each cell.
For example, I have the following image where it shows three cells and the subviews in each cell. For this example, all of the cells have data for subview 1, so it shows up in all of them. But only the first two cells have data for subview 2, so it only shows up in those cell. Likewise, subview 3 only shows up in the first cell because that is the only cell that has data for that subview. Now for subview 4, none of the cells have data for it, so it is completely skipped and there is no space taken up in any cell to render it. Instead, subview 5 is rendered in the place where subview 4 would normally have been rendered and it is only in the third cell because only that cell had data for it.
I also have dashed lines between the subviews showing that they are supposed to be lined up across cells.
Question
So I am just curious what the best way to do something like this is, given these requirements. Could this be done with AutoLayout or do I need to manually layout these subviews?
The only way I can think of doing this currently is to iterate through all of the model objects, try to figure out how tall each subview is and essentially keep track of the tallest height for each subview. And if no cell has data for a particular subview, the height of that one would be zero.
Next, I would turn those heights into computed offsets for each subview, where the computed offset would be the sum of the heights of the subviews above it and the spacing between each subview.
Then, I would try to lay these out manually, I suppose, with the frame of each subview being set to some width (not sure how to calculate the optimal width of each subview) and a vertical position equal to the computed offset of that subview. Or I guess I could do AutoLayout as well where the top constraint on a field is equal to the computed offset for each subview, but is that less efficient?
And then I guess the height of each cell would be just the computed offset of the last item plus its height plus the spacing to the bottom of the cell. So then I would take the max height of all the cells and set all of the cells to the same height.
But I was just curious if there was a better way of doing this or if there was anything that I was overlooking that could simplify things. I would also like this to be as efficient as possible as the collection view could have up to 100 items in it.
You will need to loop through your data, calculating the "max height" for each item.
I'd suggest putting your 5 "views" in a vertical stack view.
As you loop through your data, get the max height for each of the 5 views. Then, when you set your data in each cell, set the height constraint on each of the 5 views (or, set a view hidden if it is nil in all data items).
Then set your collection view's height to the necessary height to fit all the views plus spacing.
I have Viewcontroller in which I set the scrollview. In the scrollview I have tableview which is in the Container and just below the container I have an textview and some other UIViews when I set the tableview frame size equal to content size and tableview scroll property false so that only scrollview scrolls when the content size increase the textview goes up to tableview and I want that when tableview content increase then textview also goes down and parent view frame size increase and decrease as the content size
This look like a job for a UICollectionViewController. If you want to take a look here
you can get a better understanding of what they are and how to use them.
Basically you want to put each of those UITableViews, UILabels and the UIButtons in it's own cell(buttons need to be arranged) of the collectionView then the cell with the buttons try to use a stack view with the image. This will automatically set the different sections apart from each other. I know the idea of a collectionViewCell containing a tableView may seem weird but check this out
Another solution is to get crazy with constraints and autoLayout. I don't recommend this route because autoLayout will make decisions on it's own if the exact layout is not explicitly declared. Basically you'll set the constraints by pinning the tableView and labels to each other and the container they are in.
Checkout Apple's docs here
Good luck and let me know how it goes
I would recommend using a xib (if storyboards is your preference) or programmatically embed a tableview in the Scrollview Controller. Set a default cell height and then calculate the height of the Tableview by grabbing the amount of cells (which you'll normally get from .count in an array).
Afterwards, constrain the top, left, and right constraints of the tableview to its parent. You can imbed these in a scroll view for ease. Then if you want default text underneath it, all you have to do is constrain the top of the textview to the bottom of the tableview.
Do the cell for the button's. As the post above said, buttons might be best done in a CollectionView, so you can either create a default cell (xib again is useful) or use a prototype cell in storyboard. Collection views are the same principle as tableviews when it comes to populating data, they are just formatted differently and insets/spacing between cells.
This should help!
I'm working on an app that will populate the tableview based on a web service response. So far the two content types I know I will be getting will be data shown in a textview, and also in a collection view. I've begun implementing Ash Furrow's AFCollectionView. The dynamic sizing for text areas is working, however the collection view is scrolling within a cell height that is even less than my estimatedRowHeight (210.0).
Because the collection view table cell is not correctly resizing is it possible to explicitly set the height for the collectionView cell(s), and let any of the text based cells remain dynamic?
Your self sizing cells use auto-layout to determine what height to be, and that's based on the intrinsic content size of the subviews. But, that's not the only way auto-layout can specify the height of a view. You can add a static height constraint to your cells which contain a collection view.
I have 3 labels in a UITableViewCell and have the labels set so they will wordwrap. If they word wrap the text goes into the next cell. How do I get AutoLayout to expand the cell based on the content without having to write code in the heightForRowAtIndex method? Isn't there a constraint I can use to automatically adjust the cell based on the contentView?
The cell looks fine if the text doesn't wrap in the label. Once it wraps that is when the problem occurs and I would like to have the cell resize to fit the content and have the same spacing between the bottom label and the bottom as there is between the top and top label.
Unfortunately no, you can't do this. A table view calculates its own total height first and has a fixed idea of the size of each cell as they load, it won't determine it's height from the outside in and it won't let layout constraints change the height of a cell.
If you think about how tables work, with cell reuse, then you couldn't really size the table from its cells without loading in every cell and adding it to the scrollview, and performing a layout pass on the whole thing. That would probably lead to quite poor performance.
You could experiment with populating a "free" cell (i.e a cell you've just instantiated, not added to a table) and laying it out for each row in your datasource when calculating heightForRow.
As you are loading the individual cells, after you fill the labels, but before you load the instance of the cell, check the label height.
Something like:
cell.frame.size.height
If the height is large enough that you know the label has wrapped to two lines, then increase the height of the cell you are about to load.
I am trying to achieve a newsstand like effect with a scrolling and repeating background. I could do this using a UITableView if I could set it's content size (An inherited method that seems to be overridden by something else in the UITableView Code) in order to fill the view with unscrollable cells.
Currently I am planning to make a custom uiscrollview. Which will be more complex and won't have the cell reuse.
So, is there a way to set a UITableView's content size.
You could semi-hack a 'contentSize' kind of control over a UITableView by simply setting the number of cells that you have (let's assume you have a 1 section table view and aren't using a 'grouped' styled table) to:
your desired height contentSize height / height for each cell (default is 44)
Now, your problem is that if you only have, say, three rows' worth of data to display, what to do with the rest of the cells? Well, simply set their backgroundColor to the same as the table's background color and their selectionStyle property to UITableViewCellSelectionStyleNone. Wham, now you have invisible cells, and can set the 'contentSize' of the table.
Note that your contentSize will only have a resolution of the height of your cells, if you leave the cell heights at their default 44, then you can only set the contentSize to a multiple of 44.