Make UICollectionViewFlowLayout not centering cells on the same line - ios

According to Apple Documents:
If you want to specify different sizes for your cells, you must implement the collectionView:layout:sizeForItemAtIndexPath: method on the collection view delegate. You can use the provided index path information to return the size of the corresponding item. During layout, the flow layout object centers items vertically on the same line, as shown in Figure 3-2. The overall height or width of the line is then determined by the largest item in that dimension.
https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/UsingtheFlowLayout/UsingtheFlowLayout.html#//apple_ref/doc/uid/TP40012334-CH3-SW1
Now I have a collection view with 2 columns and cells varying in height. The problem is that the smaller cell is centered with the taller cell on its left/right, but not float up with the cell under it floats up too.
How can I make that happen?
What I have:
What I want:
It seems like that I should subclass UICollectionViewFlowLayout, but how should I accomplish this?

The type of collection view layout you desire is called "waterfall layout". The implementation is a little bit tricky, since you need to override the basic behaviour of UICollectionViewFlowLayout.
I suggest you to take a look at this tutorial by Ray Wenderlich for building a waterfall layout from the ground, or - if you desire an already packed library - using a library on GitHub, like CHTCollectionViewWaterfallLayout, WaterfallCollectionView or CollectionViewWaterfallLayout

What you want to achieve is called "staggered layout". It was introduced by Pinterest in their iOS app.
You will need custom collection view layout, this tutorial will explain how. Alternatively, you can use one of the existing solutions, for example CHTCollectionViewWaterfallLayout.

Related

How to make a grid layout in iOS?

I want to make a kind of grid layout (not scrollable) in an iOS app, similar to this:
I can do it using multiple UIView but that won't be a good solution. If I use `UICollectionView', I believe it will become scrollable? I want fixed grid items, which resize them according to screen size.
Any guidelines please?
Thanks!
You should use collection view with scrolling and bouncing disable.
It is all about your collectionview's flowlayout's item size.
You have to calculate item size receptively your screen's size.
And you can set that item size to flowlayout and can use that flowlayout with your collection view.
For example, You can refer this so post.
If you just want fixed 3x2 layout scaling to any screen size then multiple UIView is a good solution for this and exactly what you should do.
Also make a RestaurantView UIView subclass to configure and display the image/rating/title/description/etc details for each restaurant.
-
If you want the number of restaurants to change depending on screensize then use a UICollectionView with ResturantCollectionViewCell instead.

UITableView height for dynamic cells

In my current project i'm trying to display data in a table View, however the former view does not take up the whole screen just a part of it. It's number of cells depends on an external json and the height of the cell is dynamic. Sadly there is no inbuilt way to use auto-layout(at least i think there's not) to expand the tableView depending on it's cells.
In the following picture there's an example of how one of these table views should look like:
And here's an example how the table view looks like using the autolayout:
Is there a way to expand the tableView to it's full size?
I've tried to follow various other questions but none have fully helped me, for exampled i've tried to this solution which sadly did not help me :[, creating a subclass of uitableview and overriding its intrinsicContentSize did not do the trick either.
Any help is much appreciated.
-Jorge :]

Randomly sized UICollectionViewCell circle design

I want to have a collection view with randomly sized cells but each cell is circle. An example mockup is shown below.. The question is
how would I go about doing this?
Edit: The design doesn't have to be a UICollectionView, I just assumed this would be the best way to do it.. I'm definitely open to any way about doing this.
I also think using a UICollectionView is a good idea. You would definitely have to implement a custom flow layout to be able to organize these random sized cells. Maybe taking a look at CCHexagonFlowLayout and MosaicLayout could help. As for drawing the circles inside the cells, you could have a square UIView in the cell and set circleView.layer.cornerRadius to half of its height.
The collection view is a pretty good idea. Using the flow layout, you can implement collectionView:layout:sizeForItemAtIndexPath:. Answer a random square size (see arc4random_uniform()).
Within each cell, inscribe a circle. The simplest way to do that (at least for a start) is a UIImageView whose frame fills the cell bounds and whose content mode is set to UIViewContentModeScaleAspectFit. All you need then is a picture of a circle.

How to enable scroll in UICollectionView?

I’m still learning to develop in iOS and Swift so I apologize beforehand if my question is too simple.
I have created an UICollectionViewController to show a matrix of elements. My issue is that the width of the screen is not wide enough to fit all the columns in a single row, so the excess of them are shown in another row below. Instead of this, I’d like to enable the horizontal scroll so the user can scroll to see all the columns in one single row.
I know UICollectionViewController already contains UIScrollView so I guess this should be as simple as to change a setting in the .storyboard but I couldn’t find it after many trial-errors :(
I guess it is related to the "Flow" layouts setting and that I need to handle a custom one, but don't know how exactly.
Would anyone be so kind to please help me? I haven’t attached any code because I’m using a pretty standard/out-of-the-box implementation of UICollectionViewController but if you want me to add anything, just let me know, please.
Many thanks in advance for any help!
I found the answer to my issue perfectly covered on this post:
https://www.credera.com/blog/mobile-applications-and-web/building-a-multi-directional-uicollectionview-in-swift/
It's definitely to do with your UICollectionViewLayout — that tells the collection view where everything should go. The collection view simply picks its scroll behaviour appropriately.
A UICollectionViewFlowLayout is a specific type of layout that fills one row column to the size of the enclosing view, then moves on to the next. So it does one-dimensional scrolling. Does that fit your use case?
If so then you should just be able to set the scroll direction on the flow layout.
If not then you'll need to write a custom subclass of UICollectionViewLayout that implements the layout behaviour you want.

UICollectionViewFlowLayout vs subclassing UICollectionViewLayout

I know the documented advice is to use UICollectionViewFlowLayout if you are doing anything "like a grid or a line-based breaking layout". However, I am not sure this is true for my case.
I want a grid but do not want a line-breaking layout. Items should be laid out infinitely both horizontally and vertically without ever stacking. Essentially, a giant chessboard that scrolls horizontally or vertically if content goes beyond the frame.
To subclass UICollectionViewFlowLayout I would have to:
Override prepareLayout to stop the layout from wrapping items. This seems like a lot of work.
Override collectionViewContentSize.
Apple says they have done "lots of hard work" in crafting UICollectionViewFlowLayout, so I should leverage it if I can. But if I have to override prepareLayout to turn off line-breaking, I suspect that I am throwing away a large part of their work. Of their work that is left, I probably will not use most of it anyway (for example, minimumLineSpacingForSectionAtIndex).
Because the layout I want is so simple, I suspect that I should subclass UICollectionViewLayout instead, because:
I will have a simpler and cleaner implementation with everything in one layout class instead of spread between a subclass and a delegate.
I don't think it will be that much harder than subclassing UICollectionViewFlowLayout because I have to override prepareLayout in both cases, and I suspect that is where all the hard work will be.
I'll be in a better position to tweak other UICollectionViewLayoutAttributes in custom ways than trying to add another kludge on top of a UICollectionViewFlowLayout subclass.
Is my conclusion correct?
UICollectionViewFlowLayout can't support two directions anyway, it scrolls along one axis only, either horizontally or vertically. So you have to subclass UICollectionViewLayout not UICollectionViewFlowLayout.
Then you have to override prepareForLayout, layoutsAttributesForElementsInRect methods as you said correctly..
The layout you describe (items arranged in an indefinitely long horizontal line and sections arranged in an indefinitely long vertical line) resembles the "featured" section of the App Store :)
I have been meaning to use a similar concept in some of my apps too, and I think the trick here is that it's not handled by a single UICollectionView. It appears that what you are looking for can be achieved by using a UITableView as a base, and have each section of your content take up a single cell in the table. That is, each UITableViewCell would contain a UICollectionView with horizontal scrolling.
The key limitation of UICollectionView that is sometimes not trivial to understand is that it is, after all, a single scrollView. You can override some functionality to enable scrolling in both directions, but if you want some content to scroll one way, and some content to scroll another way, you would have to create nested scrollViews.

Resources