How to change background color of a whole section

2019-01-22 07:09发布

问题:

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?

回答1:

This is a great tutorial for changing UICollectionView section color:

Updated link, thanks to user @casamia

http://www.ericjchapman.com/jekyll/update/ios/2014/11/10/ios-changing-section-background-color-in-UICollectionView.html

Basically, we will have to subclass UICollectionViewLayoutAttributes, UICollectionReusableView and UICollectionViewLayout in order to create a instance UICollectionReusableView as section's background view.

This is his result:

Please follow the link for more details explanation.



回答2:

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:.



回答3:

The idea is to override UICollectionViewLayoutAttributes to add a color attribute. And then override UICollectionReusableView apply the color to the view background.

https://github.com/strawberrycode/SCSectionBackground



回答4:

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.



回答5:

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.



回答6:

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;
}