在 UICollectionView 中,我想为整个部分提供统一的背景颜色,而不是为单个单元格或整个集合视图。
我没有看到任何委托方法可以做到这一点,有什么建议吗?
在 UICollectionView 中,我想为整个部分提供统一的背景颜色,而不是为单个单元格或整个集合视图。
我没有看到任何委托方法可以做到这一点,有什么建议吗?
UICollectionViewCompositionalLayout
iOS 13 中引入的新属性有一个名为decorationItems
方便添加装饰项目的属性,您可以使用该属性为该部分添加背景。
let section = NSCollectionLayoutSection(group: group)
section.decorationItems = [
NSCollectionLayoutDecorationItem.background(elementKind:"your identifier")
]
这个想法是覆盖UICollectionViewLayoutAttributes以添加颜色属性。然后覆盖UICollectionReusableView将颜色应用于视图背景。
我还没有尝试过,但在我看来,如果你想要单元格后面的背景(比如 Books 应用程序中的书架),你需要使用装饰视图。我认为您应该能够为每个部分拥有不同的视图,并使用委托方法进行设置layoutAttributesForDecorationViewOfKind:atIndexPath:
。
首先,将 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
}
这些文档链接帮助了我:
参考:
草莓代码:使用DecorationView作为背景
devxoul:使用SupplementaryElement作为背景
airbnb:使用SupplementaryElement作为背景
我需要兼容IGListKit
,所以我decorationView
用作背景。布局是UICollectionViewFlowLayout
常见用例的子类。我的实现:
在集合视图中,每个部分都可以有一个补充视图,因此为每个部分放置补充视图,然后将背景颜色设置为补充视图而不是部分单元格。我希望它会有所帮助。
一种经典的方法是创建一个自定义补充种类并在 CollectionView 部分背景中提供您的自定义视图。它将使您能够自定义部分背景。参考https://stackoverflow.com/a/63598373/14162081
斯威夫特 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 中的高度。你应该为你自己的项目改变它。
它非常简单,只需使用这个默认的 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
}
我在以下方法中以非常简单的方式更改了每个部分的背景颜色: 但我不确定这样做是否正确。但它确实奏效了。
- (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;
}