I recently faced a small challenge on a UICollectionView
, the following screenshot illustrates pretty well the situation. In short: I needed to have a transparent background in a UICollectionView
to be able to see through some sections, but I didn’t want to be able to see the background in between the cells on some others.
Basically, I needed to be able to set different background colors per section. Well, needless to say that functionality doesn’t exist by default on iOS.
Luckily for me I found this great article: Changing the section background color in a UICollectionView from Eric Chapman who did an amazing job cutting down the layout fuss to reveal the bare minimum. As the project I’m working on is written in Swift, I transcribed and adapted it and wanted to share it with you.
Get ready to be amazed, you’re going to learn how to create a section background on UICollectionView
and add color to it!
Note: for those not used to the CollectionViewFlowLayouts
, don’t worry, I have a comprehensive article (2 articles actually) nearly ready to be published, sit tight!
The magic
The idea is to override UICollectionViewLayoutAttributes
to add a color attribute. And then override UICollectionReusableView
apply the color to the view background. Easy peasy :)
class SCSBCollectionViewLayoutAttributes : UICollectionViewLayoutAttributes { var color: UIColor = UIColor.whiteColor() override func copyWithZone(zone: NSZone) -> AnyObject { let newAttributes: SCSBCollectionViewLayoutAttributes = super.copyWithZone(zone) as! SCSBCollectionViewLayoutAttributes newAttributes.color = self.color.copyWithZone(zone) as! UIColor return newAttributes } } class SCSBCollectionReusableView : UICollectionReusableView { override func applyLayoutAttributes(layoutAttributes: UICollectionViewLayoutAttributes) { super.applyLayoutAttributes(layoutAttributes) let scLayoutAttributes = layoutAttributes as! SCSBCollectionViewLayoutAttributes self.backgroundColor = scLayoutAttributes.color } }
How to use it?
The idea is to loop over the cells in the selected section and add a background to that cell (or row, or section… your choice) and apply the color to it. In my implementation, you can even change the color by indexPath
. How flexible! All this happens in the UICollectionViewFlowLayout
used on your UIcollectionView
.
Here is an example of layoutAttributesForElementsInRect
:
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { let attributes = super.layoutAttributesForElementsInRect(rect) var allAttributes = [UICollectionViewLayoutAttributes]() if let attributes = attributes { for attr in attributes { // Look for the first item in a row // You can also calculate it by item (remove the second check in the if below and change the tmpWidth and frame origin if (attr.representedElementCategory == UICollectionElementCategory.Cell && attr.frame.origin.x == self.sectionInset.left) { // Create decoration attributes let decorationAttributes = SCSBCollectionViewLayoutAttributes(forDecorationViewOfKind: "sectionBackground", withIndexPath: attr.indexPath) // Set the color(s) if (attr.indexPath.section % 2 == 0) { decorationAttributes.color = UIColor.greenColor().colorWithAlphaComponent(0.5) } else { decorationAttributes.color = UIColor.blueColor().colorWithAlphaComponent(0.5) } // Make the decoration view span the entire row - or whatever you want ;) let tmpWidth = self.collectionView!.contentSize.width let tmpHeight = self.itemSize.height + self.minimumLineSpacing + self.sectionInset.top / 2 + self.sectionInset.bottom / 2 // or attributes.frame.size.height instead of itemSize.height if dynamic or recalculated decorationAttributes.frame = CGRectMake(0, attr.frame.origin.y - self.sectionInset.top, tmpWidth, tmpHeight) // Set the zIndex to be behind the item decorationAttributes.zIndex = attr.zIndex - 1 // Add the attribute to the list allAttributes.append(decorationAttributes) } } // Combine the items and decorations arrays allAttributes.appendContentsOf(attributes) } return allAttributes }
In my example on GitHub, I used a UICollectionView
with 4 sections, 3 cells with green background on the even sections and 7 cells on a blue background on the odd ones. Once the magic applied, I got something like that:
You can find the full code on GitHub: SCSectionBackground.
I hope that helps, and don’t hesitate to tweak, update, customize it ;)