Reputation: 957
I'm trying to setup a UICollectionViewLayout
programmatically. I'm using a UICollectionView
also without using storyboards, as well as settings its constraints.
I've followed Ray Wenderlich tutorial on the subject with some changes to adapt the code to Swift 3 (as AZCoder2 did https://github.com/AZCoder2/Pinterest).
Since all these examples uses storyboards, I've also introduced some changes to create the UICollectionView
and its UICollectionViewLayout
:
collectionViewLayout = PinterestLayout()
collectionViewLayout.delegate = self
collectionView = UICollectionView.init(frame: .zero, collectionViewLayout: collectionViewLayout)
The result: I can't see anything. If I change the UICollectionViewLayout
with the one that Apple provides (UICollectionViewFlowLayout
), at least I can see the cells with their content. If I implement some changes and use the storyboard, everything works great but it's not the way I want to accomplish this. The whole view is made programmatically and the collection view is a part of it.
What am I missing? Is it something to do with the way I instantiate the UICollectionViewLayout
? Do I have to register something (for example, as I need to register the reusable cell)?
Upvotes: 7
Views: 17062
Reputation: 1
I resolved this issue taking these steps:
1 - Changing UICollectionViewController to a UIViewController with a collectionView inside.
2 - On ViewDidLoad I set the delegates and add the view, as usual. Moreover, I instantiate the ViewLayout and use it to instantiate the CollectionView
var collectionView: UICollectionView?
override func viewDidLoad() {
super.viewDidLoad()
navigationController!.isToolbarHidden = true
let layout = MosaicViewLayout()
layout.delegate = self
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
guard let collectionView = collectionView else {
return
}
view.addSubview(collectionView)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(PhotoCell.self, forCellWithReuseIdentifier: "CharacterCell")
setupCollectionConstraints()
}
3 - On the ViewLayout the protocol stays like this:
protocol MosaicViewLayoutDelegate:class {
func collectionView(_ collectionView: UICollectionView,
heightForItemAtIndexPath indexPath: IndexPath) -> CGFloat
}
Don't forget to add the instance inside the class
weak var delegate: MosaicViewLayoutDelegate?
4 - Add the delegate extension to you ViewController
extension HomeViewImpl: MosaicViewLayoutDelegate {
func collectionView(_ collectionView: UICollectionView, heightForItemAtIndexPath indexPath: IndexPath) -> CGFloat {
let random = arc4random_uniform(4) + 1
return CGFloat(random * 100)
}
}
enter code here
Upvotes: 0
Reputation: 349
I think this will work.
override init(collectionViewLayout layout: UICollectionViewLayout) {
super.init(collectionViewLayout: layout)
collectionView?.collectionViewLayout = YourCollectionViewLayout()
}
Upvotes: 2
Reputation: 957
It's possible to do what I was trying to do. Basically, follow the tutorials I suggested in my own question and setup the collection view and its view layout as follow:
collectionViewLayout = PinterestLayout()
collectionViewLayout.delegate = self
collectionView = DynamicCollectionView.init(frame: .zero, collectionViewLayout: collectionViewLayout)
Note that I'm using DynamicCollectionView
(instead of UICollectionView
). This class is not provided by Apple: I've made my own using the code provided in this post.
Remember that this approach is when you're creating a view programmatically, using constraints. (May be it has another cases of use)
Upvotes: 1
Reputation: 5359
How about you just create a variable that creates your flow layout for you like this
var flowLayout: UICollectionViewFlowLayout {
let _flowLayout = UICollectionViewFlowLayout()
// edit properties here
_flowLayout.itemSize = CGSize(width: 98, height: 134)
_flowLayout.sectionInset = UIEdgeInsetsMake(0, 5, 0, 5)
_flowLayout.scrollDirection = UICollectionViewScrollDirection.horizontal
_flowLayout.minimumInteritemSpacing = 0.0
// edit properties here
return _flowLayout
}
And then you can set it by calling the variable.
self.collectionView.collectionViewLayout = flowLayout // after initializing it another way
// or
UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
Upvotes: 8