如何更改 UICollectionView 中整个部分的背景颜色?

Posted

技术标签:

【中文标题】如何更改 UICollectionView 中整个部分的背景颜色?【英文标题】:How to change background color of a whole section in UICollectionView? 【发布时间】:2012-11-16 13:09:08 【问题描述】:

在 UICollectionView 中,我想为整个部分提供统一的背景颜色,而不是为单个单元格或整个集合视图。

我没有看到任何委托方法可以做到这一点,有什么建议吗?

【问题讨论】:

试试这个github.com/devxoul/UICollectionViewFlexLayout 【参考方案1】:

ios 13 中引入的新UICollectionViewCompositionalLayout 有一个名为decorationItems 的属性,可以方便地添加装饰项,您可以使用该属性为该部分添加背景。

let section = NSCollectionLayoutSection(group: group)
section.decorationItems = [
   NSCollectionLayoutDecorationItem.background(elementKind:"your identifier")
]

【讨论】:

【参考方案2】:

想法是重写 UICollectionViewLayoutAttributes 以添加颜色属性。然后覆盖 UICollectionReusableView 将颜色应用到视图背景。

https://github.com/strawberrycode/SCSectionBackground

【讨论】:

当我制作这个示例以支持所有方向时,从纵向移动到横向移动或反之亦然,应用程序崩溃并出现以下错误, SCSectionBackground[34266:300939] *** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“索引路径处补充项目的布局属性(length = 2, path = 0 - 0 ) 从 索引路径: (length = 2, path = 0 - 0);元素种类:(sectionBackground);帧 = (0 0; 375 116); zIndex = -1; 不使布局无效'。你能帮忙解决这个问题吗?【参考方案3】:

我还没有尝试过,但在我看来,如果您想要单元格后面的背景(例如 Books 应用程序中的书架),则需要使用装饰视图。我认为您应该能够为每个部分拥有不同的视图,并使用委托方法 layoutAttributesForDecorationViewOfKind:atIndexPath: 进行设置。

【讨论】:

【参考方案4】:

参考:strawberrycode: Use DecorationView as backgrounddevxoul: Use SupplementaryElement as backgroundairbnb: Use SupplementaryElement as background

我需要兼容IGListKit,所以我使用decorationView作为 背景。布局是UICollectionViewFlowLayout 的子类,用于常见用例。 My implementation:

【讨论】:

【参考方案5】:

首先,将 UICollectionReusableView 作为背景视图。我只是将我的设置为红色。

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")
    

然后,在 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

这些文档链接帮助了我:

https://developer.apple.com/documentation/uikit/nscollectionlayoutdecorationitem https://developer.apple.com/documentation/uikit/uicollectionviewcompositionallayoutsectionprovider

【讨论】:

【参考方案6】:

在集合视图中,每个部分都可以有一个补充视图,因此为每个部分放置补充视图,然后将背景颜色设置为补充视图而不是部分单元格。我希望它会有所帮助。

【讨论】:

在阅读补充视图时,我只找到用于页眉和页脚的示例。您是否有任何示例和/或工作代码可供您回答。 我已经通过使用集合视图自定义布局来完成它。在自定义布局中,我的补充视图框架等于整个剖面框架。 你是怎么做到的?如果你能说那会很棒。谢谢【参考方案7】:

其中一种经典方法是创建自定义补充种类并在 CollectionView 部分背景中提供您的自定义视图。它将使您能够自定义部分背景。 参考https://***.com/a/63598373/14162081

【讨论】:

【参考方案8】:

我在这里退出了这个 repo https://github.com/SebastienMichoy/CollectionViewsDemo/tree/master/CollectionViewsDemo/Sources/Collections%20Views

斯威夫特 3

子类 uicollectionreusableview

class SectionView: UICollectionReusableView 
   static let kind = "sectionView"

子类 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


实现这个

CollectionView 委托函数

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
    

这很重要

let layout = CustomFlowLayout()
layout.register(SectionView.self, forDecorationViewOfKind: SectionView.kind)

使用布局而不是 collectionView 注册 UICollectionReusableView。

还有一件事。我弄乱了 layoutAttributesForElements 中的高度。您应该为自己的项目更改它。

【讨论】:

【参考方案9】:

很简单,只要使用这个默认的UICollectionViewDelegate的方法,就可以了

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


【讨论】:

【参考方案10】:

我通过以下方法以非常简单的方式更改了每个部分的背景颜色:但我不确定这样做是否正确。但它确实奏效了。

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

【讨论】:

这只会改变单元格的背景颜色。问题是询问如何在给定部分中更改集合视图本身的背景颜色

以上是关于如何更改 UICollectionView 中整个部分的背景颜色?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 中更改 UICollectionView 的 targetContentOffset?

如何在 iOS 中动态更改 UICollectionView 单元格高度

如何更改 UICollectionView 中的滚动方向?

如何更改 UICollectionView 中单元格之间的空间?

如何更改自定义 UICollectionView 布局引擎中的默认布局动画曲线?

设备方向更改时如何更改 UiCollectionView 单元格大小?