CollectionVIew dynamic calculation width, item display is incomplete - ios

The UICollectionView uses the calculated item attribute (estimatedItemSize) to calculate the width of the item and the layout of the Masonry used by UICollectionViewCell.m. As a result, the last Item cannot be pulled and the display is incomplete. Modifying contentInset has no effect.
Directly fixed item size can be completely displayed, guessing that the dynamic calculation does not calculate the width.
Code:
MainViewController:
HeaderCollectionView:
HeaderViewCell:

Related

How to make UICollectionViewCells with content lined up across cells

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.

iOS - Dynamic height, data driven, vertically scrollable layout

I am trying to create the layout in the image
Here is the main requirements:
The content in each section is data driven and retrieved from the api.
The height of each section is dynamic, based on how many fields we have.
The scene height is dynamic.
The scene is vertically scrollable.
Here is what I tried to do:
- Using static cell UITableView
- Using stack view with a scroll view
In both cases I got stuck with dealing with stack views for the dynamic data fields, and I struggled in handling the dynamic height for each section.
Any Ideas?
Your requirement is pretty straight forward and can be met using a UITableView. Use dynamic UITableViewCell. The reason i choose dynamic table view cell is that you can resize the cell height according to content. Measure your content size inside the tableView:heightForRowAtIndexPath:.
The flow will be following:
Initiate the api call
While the data isn't available return the cell height according to your placeholder view (i.e placeholder image height)
While the data is available, process your data and reload the table view
After reloading the table view, table view will ask each cell's height once again, so this is the chance you get to calculate the content height. (I assume that you can measure the string height while the string width and font is given. Plz google that, thats obvious.)
return that calculated height.
Optimization Possibilities:
Instead of recalculating the cell height each time, you can calculate the cell height once and store that height inside a simple dictionary keyed with IndexPath.

Attach/Stick a UIButton under the UITableView

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.

Display one row in UICollectionView - Swift

I'm trying to figure out how to limit a UICollectionView to display a horizontal scrollable list in a single row.
Any Ideas?
I just used something that is working for me:
Set the Scroll direction to Horizontal.
Set the size of your Cells using sizeForItemAt indexPath method.
Set a constraint to your CollectionView making its height equal to (or a bit greater than) the Cell's height which you specified above.
The logic behind it:
When the height of CollectionView is equal to the height of it's items and it is set to horizontal scroll, then it can only show them in one row. I said "or a bit greater than cell's height" because if you set the height of your CollectionView twice bigger than cell's height then it can fit 2 rows of cells and it will show them in 2 rows instead of one.

Label on collection view header should be positioned above a specific cell

I want to have a label above a certain position in my collection view. Thereby the label can have a different size. For this I thought I use the supplementary views - namely the header. An example of this behavior can be seen in the iOS calendar:
The month name is either written in short form it the available space is scarce (last column) or written with the full name if you have more space. Also the month name starts with the first of a month.
What I can think of is to create a supplementary view, pass the content view size and calculates the distance from the side by multiplying the number of cells with the cell width. The cell width is calculated through the set collection view size and the data in the header defines the number of the cell. But what about orientation change and things like that? You can't use a cells header because the label can go over multiple cells.
How would you implement such a header?
Solution:
I used container each having the same width. On this container I added my labels. Now I can configure to either center the labels or position them at the beginning of the container. It now works for all orientations! Thanks rdelmar for leading me to this idea!

Resources