In UICollectionView, I want to give the whole section a uniform background color, instead of for a single cell or for the whole collection view.
I don't see any delegate method to do that, any suggestions?
In UICollectionView, I want to give the whole section a uniform background color, instead of for a single cell or for the whole collection view.
I don't see any delegate method to do that, any suggestions?
First, make a UICollectionReusableView to be your background view. I've simply set mine to be red.
class SectionBackgroundDecorationView: UICollectionReusableView {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = .red
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Then, in YourCollectionViewController:
static let background = "background-element-kind"
init() {
super.init(collectionViewLayout: YourCollectionViewController.createLayout())
}
static func createLayout() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int,
layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
// Use sectionIndex to control the layout in each section
if sectionIndex == 0 {
// Customise itemSize, item, groupSize, group to be whatever you want
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1),
heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1),
heightDimension: .absolute(170))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
// Create a sectionBackground
let sectionBackground = NSCollectionLayoutDecorationItem.background(
elementKind: background)
section.decorationItems = [sectionBackground]
return section
} else {
// Your layout for other sections, etc
// You don't have to set a background for other sections if you don't want to
}
}
layout.register(SectionBackgroundDecorationView.self, forDecorationViewOfKind: background)
return layout
}
These links to documentation helped me:
The new UICollectionViewCompositionalLayout
introduced in iOS 13 have a property named decorationItems
for adding decoration items conveniently, which you could use to add a background for the section.
let section = NSCollectionLayoutSection(group: group)
section.decorationItems = [
NSCollectionLayoutDecorationItem.background(elementKind:"your identifier")
]
group
and how do you obtain it for a given section. This doesn't explain how you use it at all. –
Archery The idea is to override UICollectionViewLayoutAttributes to add a color attribute. And then override UICollectionReusableView apply the color to the view background.
I haven't tried this out yet, but it looks to me that you need to use decoration views if you want a background behind your cells (like the shelf in the Books app). I think you should be able to have different views for each section, and set them up using the delegate method layoutAttributesForDecorationViewOfKind:atIndexPath:
.
refer to:
strawberrycode: Use DecorationView as
background
devxoul: Use SupplementaryElement as background
airbnb: Use SupplementaryElement as background
I need to compatible with IGListKit
, so I use decorationView
as
background. The layout is subclass from UICollectionViewFlowLayout
for common use case. My implementation:
In collection view every section can have a supplementary views, so put supplementary views for each section then set background color to supplementary views instead of section cells. I hope it will help.
One of the classic approach is to create a Custom Supplementary Kind and provide your custom view in CollectionView Section background. It will give you the ability to customize section backgrounds. Refer to https://mcmap.net/q/371946/-how-to-add-a-background-image-to-uicollectionview-that-will-scroll-and-zoom-will-cells
I went off of this repo here https://github.com/SebastienMichoy/CollectionViewsDemo/tree/master/CollectionViewsDemo/Sources/Collections%20Views
Swift 3
subclass uicollectionreusableview
class SectionView: UICollectionReusableView {
static let kind = "sectionView"
}
subclass uicollectionViewFlowLayout
class CustomFlowLayout: UICollectionViewFlowLayout {
// MARK: Properties
var decorationAttributes: [IndexPath: UICollectionViewLayoutAttributes]
var sectionsWidthOrHeight: [IndexPath: CGFloat]
// MARK: Initialization
override init() {
self.decorationAttributes = [:]
self.sectionsWidthOrHeight = [:]
super.init()
}
required init?(coder aDecoder: NSCoder) {
self.decorationAttributes = [:]
self.sectionsWidthOrHeight = [:]
super.init(coder: aDecoder)
}
// MARK: Providing Layout Attributes
override func layoutAttributesForDecorationView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return self.decorationAttributes[indexPath]
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var attributes = super.layoutAttributesForElements(in: rect)
let numberOfSections = self.collectionView!.numberOfSections
var xOrYOffset = 0 as CGFloat
for sectionNumber in 0 ..< numberOfSections {
let indexPath = IndexPath(row: 0, section: sectionNumber)
let numberOfItems = self.collectionView?.numberOfItems(inSection: sectionNumber)
let sectionWidthOrHeight = numberOfItems == 0 ? UIScreen.main.bounds.height : collectionViewContentSize.height//self.sectionsWidthOrHeight[indexPath]!
let decorationAttribute = UICollectionViewLayoutAttributes(forDecorationViewOfKind: SectionView.kind, with: indexPath)
decorationAttribute.zIndex = -1
if self.scrollDirection == .vertical {
decorationAttribute.frame = CGRect(x: 0, y: xOrYOffset, width: self.collectionViewContentSize.width, height: sectionWidthOrHeight)
} else {
decorationAttribute.frame = CGRect(x: xOrYOffset, y: 0, width: sectionWidthOrHeight, height: self.collectionViewContentSize.height)
}
xOrYOffset += sectionWidthOrHeight
attributes?.append(decorationAttribute)
self.decorationAttributes[indexPath] = decorationAttribute
}
return attributes
}
}
implement this
CollectionView delegate function
func collectionView(_ collectionView: UICollectionView, willDisplaySupplementaryView view: UICollectionReusableView, forElementKind elementKind: String, at indexPath: IndexPath) {
Log.printLog(identifier: elementKind, message: indexPath)
if elementKind == UICollectionElementKindSectionHeader, let view = view as? ProfileViewHeaderView {
view.backgroundColor = UIColor(red: (102 / 255.0), green: (169 / 255.0), blue: (251 / 255.0), alpha: 1)
} else if elementKind == SectionView.kind {
let evenSectionColor = UIColor.black
let oddSectionColor = UIColor.red
view.backgroundColor = (indexPath.section % 2 == 0) ? evenSectionColor : oddSectionColor
}
}
This is important
let layout = CustomFlowLayout()
layout.register(SectionView.self, forDecorationViewOfKind: SectionView.kind)
register the UICollectionReusableView with layout not collectionView.
one more thing. I messed around with the height in layoutAttributesForElements. you should change it for your own project.
Its very simple just use this default UICollectionViewDelegate's method, it will works
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
print(indexPath.item)
let evenSectionColor = UIColor.clear
let oddSectionColor = UIColor.white
cell.contentView.backgroundColor = (indexPath.item % 2 == 0) ? evenSectionColor : oddSectionColor
}
I have changed the background color of each section in a very simple manner in the following method: But I was not sure whether it is the right thing to do. But it did work.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FamilyCalendarCellItemCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"calendarItem" forIndexPath:indexPath];
Event *event;
_headerView = [collectionView dequeueReusableSupplementaryViewOfKind:
UICollectionElementKindSectionHeader withReuseIdentifier:@"EventHeader" forIndexPath:indexPath]; //headerView is declared as property of Collection Reusable View class
if(indexPath.section==0) {
cell.backgroundColor=[UIColor orangeColor];
}
else if(indexPath.section==1) {
cell.backgroundColor=[UIColor yellowColor];
}
return cell;
}
© 2022 - 2024 — McMap. All rights reserved.