I am using IGListKit library(IGListKit). I would like to create a two column collection view list like below. I have read the IGListKit manual, but I couldn't understand how to achieve that.
I passed the proper width in sizeForItem
, but the column becomes 1.
Could you give me any advice ?
Additional Info
Following is my code and its output screenshot.
First code is ViewController.
class ViewController: UIViewController {
lazy var adapter: ListAdapter = {
return ListAdapter(updater: ListAdapterUpdater(), viewController: self)
}()
@IBOutlet weak var collectionView: UICollectionView!
let channels = [
Channel(id: "1", color: UIColor.black),
Channel(id: "2", color: UIColor.blue),
Channel(id: "3", color: UIColor.red),
Channel(id: "4", color: UIColor.yellow),
Channel(id: "5", color: UIColor.green),
]
override func viewDidLoad() {
super.viewDidLoad()
self.adapter.collectionView = self.collectionView
self.adapter.dataSource = self
}
func objects(for listAdapter: ListAdapter) -> [ListDiffable] {
return self.channels as! [ListDiffable]
}
func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {
return ChannelSectionController()
}
func emptyView(for listAdapter: ListAdapter) -> UIView? {
return nil
}
Following is SectionController.
final class ChannelSectionController: ListSectionController {
var channel: Channel?
override func numberOfItems() -> Int {
return 1
}
override func sizeForItem(at index: Int) -> CGSize {
let length = collectionContext!.containerSize.width / 4
return CGSize(width: length, height: length)
}
override func cellForItem(at index: Int) -> UICollectionViewCell {
guard let channel = channel else {
fatalError("channel is nil.")
}
guard let cell = self.collectionContext?.dequeueReusableCellFromStoryboard(withIdentifier: "ChannelCell", for: self, at: index) as? ChannelCollectionViewCell else {
fatalError()
}
cell.channel = channel // Update the cell label and color.
return cell
}
override func didUpdate(to object: Any) {
self.channel = object as? Channel
}
override func didSelectItem(at index: Int) {}
}
As you can see, width which is returned in sizeForItem()
is enough small than frame width.
However, the output column becomes one line.
Based on this article(at the bottom) how to create an object you should create your object like this:
class ChannelCollection: ListDiffable {
var id : String
var channels: [Channel]
init(id: String,channels: [Channel]) {
self.id = id
self.channels = channels
}
func isEqual(toDiffableObject object: ListDiffable?) -> Bool {
return true //compare your object here, I returned true for test
}
func diffIdentifier() -> NSObjectProtocol {
return id as NSObjectProtocol
}
}
and your viewcontroller should look like this:
class ViewController: UIViewController,ListAdapterDataSource {
lazy var adapter: ListAdapter = {
return ListAdapter(updater: ListAdapterUpdater(), viewController: self)
}()
var items : [Any] = []
@IBOutlet weak var collectionView: UICollectionView!
var channelCollection : ChannelCollection?
let channels = [
Channel(id: "1", color: UIColor.black),
Channel(id: "2", color: UIColor.blue),
Channel(id: "3", color: UIColor.red),
Channel(id: "4", color: UIColor.yellow),
Channel(id: "5", color: UIColor.green),
]
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.frame = view.bounds
}
override func viewDidLoad() {
super.viewDidLoad()
self.channelCollection = ChannelCollection.init(id: "1", channels: self.channels)
self.items.append(self.channelCollection as Any)
self.adapter.collectionView = self.collectionView
self.adapter.dataSource = self
}
func objects(for listAdapter: ListAdapter) -> [ListDiffable] {
return self.items as! [ListDiffable]
}
func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {
return ChannelSectionController.init(channelCollection: self.channelCollection!)
}
func emptyView(for listAdapter: ListAdapter) -> UIView? {
return nil
}}
your ListSectionController:
final class ChannelSectionController: ListSectionController {
var channel: Channel?
var channelCollection : ChannelCollection?
init(channelCollection: ChannelCollection)
{
self.channelCollection = channelCollection
}
override func numberOfItems() -> Int {
return (self.channelCollection?.channels.count)!
}
override func sizeForItem(at index: Int) -> CGSize {
let length = collectionContext!.containerSize.width / 4
return CGSize(width: length, height: length)
}
override func cellForItem(at index: Int) -> UICollectionViewCell {
guard let cell = self.collectionContext?.dequeueReusableCellFromStoryboard(withIdentifier: "ChannelCell", for: self, at: index) as? ChannelCollectionViewCell else {
fatalError()
}
//cell.channel = channel // Update the cell label and color.
return cell
}
override func didUpdate(to object: Any) {
self.channel = object as? Channel
}
override func didSelectItem(at index: Int) {}}
So what I changed here is that you are adding 5 sections,better practice is to add a single section and 5 rows,this code outputs the thing you want,just try it.