Inserting a UICollectionView into a UITableViewCell
In apps like Spotify, the App Store, and even the Artsy app, having a collection view within a table view cell has become a frequent design trend. It's convenient to have a vertical list of items (the table view), each of which has a horizontal list (the collection view).
(As with most things in programming, a little planning ahead of time may save a lot of time later, so think about what we want to achieve first.)
If we take a step back and consider this from the standpoint of the user interface, we can have a better idea of how we might arrange our code.
Inserting a UICollectionView into a UITableViewCellIn apps like Spotify, the App Store, and even the Artsy app, having a collection view within a table view cell has become a frequent design trend. It's convenient to have a vertical list of items (the table view), each of which has a horizontal list (the collection view). (As with most things in programming, a little planning ahead of time may save a lot of time later, so think about what we want to achieve first.)If we take a step back and consider this from the standpoint of the user interface, we can have a better idea of how we might arrange our code.As a result, collection view cells are contained within the collection view (just like they normally do). Furthermore, each collection view takes up the whole table view cell (an entire row of the table view). The table view cells are then contained within the table view (again, just like normal).Okay, that's OK. The only oddity here is the collection view contained within a table view cell. That's uncommon, but given that they're all UIViews, it's quite feasible. Connecting the collection views to a data source is the most challenging aspect.
There are two main approaches to this problem. You may either retain the data for the collection view data source in the table view cell or keep it in the view controller and find a method to differentiate between the collection views. Thefirst solution appears to be the most straightforward, but it violates the Model-View-Controller principle, which states that views should not have direct access to models. Let's choose the second technique, which is more MVC-compliant.
As a result, our view controller will serve as a datasource and delegate for both the table and collection views.
A collection view's data source is frequently the view controller. We only have one view controller but numerous collection views, which is an issue. We need a means to distinguish between a collection view on the first row, a collection view on the second row, a collection view on the third row, and a collection view on the fourth row...
A mechanism to remember which table view cell a collection view is in is required. I simply need to know which row my collection view is on because my table view only has one part. A row is nothing more than an integer.
UIView contains a handy property: tag, as luck would have it. Tag is described as follows in the documentation.An integer that your application can use to identify view objects.
This will be ideal for keeping track of which row the collection view belongs to. So, it appears that we've devised a three-part strategy: a view controller class, a table view cell class, and a storyboard to tie it all together. Let's get started!
So create a table view by dragging a "Table View Controller" into the storyboard. Create a swift file with a UITableViewController To utilise this new class, subclass it and set the custom class attribute in the storyboard.
Next, give your table view cell a reusable identifier (I used "Cell") and, if desired, a custom height (I used 88pt). Create a new swift file for your project as well. UITableViewCell Set the prototype cell's custom class by subclassing it.
Drag a collection view onto the cell (it will become a subview of the cell's content view thanks to Xcode). To make autolayout work, resize it to cover the whole cell and press "add missing constraints." The hierarchy of your views should look something like this:
The only thing left is to set up the collection view. To make the cells vertically centred, I adjusted the size, spacing, and content insets. I also changed the scroll orientation to "horizontal," disabled the "Shows Horizontal Indicator," andchanged the background colour to white.
Finally, I set the reuse identifier of the collection view cell to “Cell” (it needs to be something). And that’s it for our storyboard configuration. On to the code!
It's time to code now that we've set up and setup our interface. Our: UITableViewCell subclass may be used to open the file. One attribute will be added: a reference to the collection view.
class TableViewCell: UITableViewCell {
@IBOutlet private weak var collectionView: UICollectionView!
}
In the storyboard, link this collection view output to the cell's collection view.
This is a typical IBOutlet with the exception that it has been designated as private. This is to keep our view controller from accessing the collection view through the table view cell.
Instead, we'll write a method to configure the collection view's delegate, datasource, and row number.
Override func layoutSubView{
collectionView.delegate = self
collectionView.dataSource = self
}
Now in your main view controller :
Override func layoutSubView{
collectionView.delegate = self
collectionView.dataSource = self
}
Now you have to put their delegate and datasource in viewDidLoad() :
Override func viewDidLoad(){
tableView.delegate = self
tableView.dataSource = self
}
Now we have to put there delegate and datasource protocol to load table view cell in table view :
func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return model.count
}
func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell",
forIndexPath: indexPath)
return cell
}
Now in TableViewCell we have to load the collection view with CollectionViewCell :
extension TableViewCell: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell",
forIndexPath: indexPath)
return cell
}
}