Force UICollectionView to scroll until a specific cell is centered - ios

First of all, I already read How to force UICollectionView with fewer items to scroll? and it did not solve my problem.
I have an horizontal UICollectionView with 5 cells, and only 5 cells are needed to fill the screen width. This means the 3rd cell is centered. How can I scroll so the 4th cell is centered?
When using scrollToItemAtIndexPath, it won't scroll since there is not enough cells to scroll. In other words, if I want my 4th cell to be centered, there would be a blank space at the end since I only have 5 cells (and vice-versa for the 2nd cell).
Is adding empty cells the only solution?

You could adjust the insets on the collection view. Add enough space that you can center the last cell.
More info from Apple

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.

Issues with dynamic height for UITableViewCell with UIStackView while scrolling up

I have a table view with cells with dynamic heights. Inside each cell, I have an image view and a group of 4 labels in a vertical stack view. When I first load the tableview, the cells look fine and the height is calculated correctly. This is also true for the cells that load after scrolling downwards. However, as soon as I scroll up, the height of the cell becomes huge (bigger than the entire screen).
Im not sure why this happens only when I scroll up.
tableview after initial loading
tableview after scrolling upwards
I set the spacing parameter for UIStackView to a value not 0 and it worked!

Scrolling / static UITableView footer

I want to have a UITableViewCell with a behaviour mixed between a section footer and the table footer:
If the table is not filled (meaning there are not enough cells to fill the entire screen), the cell should stay at the bottom of the table, anchored to the screen edge, leaving blank space between itself and those above. (behaving like a table footer)
If the table is filled, the cell should start scrolling and always remain at the bottom of the table. (behaving like a section footer)
I'd like to avoid as much as possible weird tricks to achieve this, is there an elegant solution that allows me to do this?
Make your footer a separate view on top of the tableView with a constraint to the bottom of the tableView and take an outlet to this constraint. Override scrollViewDidScroll and get the bottom y coordinate of the last visible cell by using tableView.visible cells and calling CGRect.maxy on its frame (if there is no last cell your constraint constant is tableView.frame.size.height - footerView.frames.size.height). Take the difference of the tableView.frame.maxY and the last visible cell's maxY. If the cell is past the tableView.frame.maxY - footerView.frames.size.height then you set your constraint constant to 0, otherwise you set it to the difference.
This has the effect of pinning your footer view to the last visible cell, unless this would force the footer past the bottom of the table, in which case you just pin it to the bottom of the table instead. If there is no last cell you pin the footer to the top of the table.

UICollectionViewCell side-by-side

I have UICollectionView in my custom keyboard, and it has two rows of cells with same heights, but different widths (size comes from server), direction of scroll is horizontal.
How can I show collection items side by side, without this strange centering which based on the previous cell width?
I've achivied needed result with SKRaggyCollectionViewLayout
P.S. If you'll use SKRaggyCollectionViewLayout, don't forget to put
self.layout.variableFrontierHeight = NO; to have same heights for all cells.

How to find the height of the tableView left over by the cells?

I have a tableview where some gap is left after the cells are over.
I would like the table's footer to take that space.
How do I accomplish this ?
The footer of a table is automatically displayed after the last of the cells. If you want to make sure that the footer fills all possible space from the last cell to the bottom of the view then just make the footer the height of the screen. If you want to dynamically arrange any subviews in your footer so that they are all visible then you probably need to add up the height of all your cells to determine how much of the footer is visible.

Resources