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

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

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

【问题讨论】:

标签: ios background-color uicollectionview


【解决方案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 background
      devxoul: Use SupplementaryElement as background
      airbnb: 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
        }
        

        这些文档链接帮助了我:

        【讨论】:

          【解决方案6】:

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

          【讨论】:

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

          其中一种经典方法是创建自定义补充种类并在 CollectionView 部分背景中提供您的自定义视图。它将使您能够自定义部分背景。 参考https://stackoverflow.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;
                }
                

                【讨论】:

                • 这只会改变单元格的背景颜色。问题是询问如何在给定部分中更改集合视图本身的背景颜色
                猜你喜欢
                • 2020-02-11
                • 1970-01-01
                • 1970-01-01
                • 2011-11-29
                • 1970-01-01
                • 1970-01-01
                • 2014-09-13
                • 1970-01-01
                • 2014-07-08
                相关资源
                最近更新 更多