Reputation: 87
I know how to display Collection cell in an UICollectionView. But I want to use a custom layout for displaying the cells.
My Collection should have two column where the width of cells is fixed, but cell's height may vary depending on label's content size.
But I don't know how to do it. I want to display the cell collection as shown in the picture below
I'd like to implement it in swift.
Upvotes: 3
Views: 8561
Reputation: 287
Following is the code for custom layout. In this layout cell width is half of the collection view and the height is specific for each cell. To set height for each cell you have to implement "func heightFor(index : Int) -> CGFloat". To implement this layout do following steps.
Create following protocol:
//This protocol has to be confirmed in your controller.
protocol CustomLayoutDelegate {
//This method accept the height for your cell.
func heightFor(index : Int) -> CGFloat
}
Create subclass "UICollectionViewFlowLayout":
class CustomLayout: UICollectionViewFlowLayout {
//Variables
var layoutDelegate : CustomLayoutDelegate?
var leftY = CGFloat(0)
var rightY = CGFloat(0)
var cache = [UICollectionViewLayoutAttributes]()
//This method sets the frame (attributes) for every cell and store in chache.
override func prepare() {
guard cache.isEmpty == true, let collectionView = collectionView else{
return
}
let verticalSpacing = CGFloat(10)
let horizontalSpacing = CGFloat(10)
let margin = CGFloat(10)
leftY = margin
rightY = margin
for item in 0..<collectionView.numberOfItems(inSection: 0){
var frame = CGRect.zero
let cellHeight = self.layoutDelegate!.heightFor(index: item)
frame.size.height = cellHeight
frame.size.width = (collectionView.frame.size.width - 2 * margin) / 2 - horizontalSpacing/2
if item%2 == 0{
frame.origin.x = margin
frame.origin.y = leftY
leftY += cellHeight + verticalSpacing
}else{
frame.origin.x = (collectionView.frame.size.width - 2 * margin) / 2 + ((4 * horizontalSpacing) / 3)
frame.origin.y = rightY
rightY += cellHeight + verticalSpacing
}
let indexPath = IndexPath(item: item, section: 0)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attributes.frame = frame
cache.append(attributes)
}
}
// This method returns the array of
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var visibleLayoutAttributes = [UICollectionViewLayoutAttributes]()
// Loop through the cache and look for items in the rect
for attributes in cache {
if attributes.frame.intersects(rect) {
visibleLayoutAttributes.append(attributes)
}
}
return visibleLayoutAttributes
}
//This method sets the collection view's content size.
override var collectionViewContentSize: CGSize{
return CGSize.init(width: collectionView!.frame.size.width, height: max(leftY, rightY))
}
}
Now, in your view controller write the following code:
import UIKit class ViewController: UIViewController,UICollectionViewDataSource, CustomLayoutDelegate {
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
//Register the cell for collection view
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
//Assign the delegate
if let layout = collectionView.collectionViewLayout as? CustomLayout{
layout.layoutDelegate = self
}
}
//CustomLayoutDelegate method
func heightFor(index: Int) -> CGFloat {
//Implement your own logic to return the height for specific cell
return CGFloat(max(1, index) * 50)
}
// UICollectionViewDataSource methods
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
cell.backgroundColor = UIColor.red
return cell
}
}
Now on your xib, Add collection view and connect to
@IBOutlate weak var collectionView: UICollectionView!
and assign our "CustomLayout" class to collection's layout:
Now, after running the project you will see the following output. Make sure collection view cell has different color, just for identification.
Upvotes: 8
Reputation: 159
Upvotes: 0
Reputation: 169
Using this function you can change the height and width of cell as you want.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize{}
use the indexPath to access the cell
Upvotes: 0