override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
//首先获取当前屏幕页面的布局信息
var superArray = super.layoutAttributesForElements(in: rect) ?? []
//通过两个for循环将s删选出已经被系统回收掉的header信息。
let nonoHeaderSections = NSMutableIndexSet.init()
for attributes in superArray {
if attributes.representedElementCategory == UICollectionView.ElementCategory.cell{
nonoHeaderSections.add(attributes.indexPath.section)
}
}
for attributes in superArray {
if attributes.representedElementKind == UICollectionView.elementKindSectionHeader {
nonoHeaderSections.remove(attributes.indexPath.section)
}
}
//确定了被回收的header信息后重复添加到布局信息的数组中
for (index, item) in nonoHeaderSections.enumerated() {
let indexPath = IndexPath.init(item: 0, section: item)
if let attributes = self.layoutAttributesForSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, at: indexPath) {
superArray.append(attributes)
}
}
//根据section中第一cell和最后一个cell的位置来确定header的位置。
for attributes in superArray {
if attributes.representedElementKind == UICollectionView.elementKindSectionHeader {
let numberOfItemsInSection = self.collectionView?.numberOfItems(inSection: attributes.indexPath.section) ?? 0
let firstItemIndexPath = IndexPath.init(item: 0, section: attributes.indexPath.section)
let lastItemIndexPath = IndexPath.init(item: max(0, numberOfItemsInSection - 1), section: attributes.indexPath.section)
var firstItemAttributes: UICollectionViewLayoutAttributes?, lastItemAttributes: UICollectionViewLayoutAttributes?
if numberOfItemsInSection > 0 {
firstItemAttributes = self.layoutAttributesForItem(at: firstItemIndexPath)
lastItemAttributes = self.layoutAttributesForItem(at: lastItemIndexPath)
}else {
firstItemAttributes = UICollectionViewLayoutAttributes.init()
let y: CGFloat = attributes.frame.maxY + self.sectionInset.top
firstItemAttributes?.frame = CGRect.init(x: 0, y: y, width: 0, height: 0)
lastItemAttributes = firstItemAttributes
}
var headerRect = attributes.frame
let currentOffset = (self.collectionView?.contentOffset.y ?? 0)
let headerY: CGFloat = (firstItemAttributes?.frame.origin.y ?? 0) - headerRect.height - self.sectionInset.top
//重点思考,在组头距离组尾很远的情况下
let finialHeaderY = max(headerY, currentOffset)
let headerMissingY = (lastItemAttributes?.frame.maxY ?? 0) + self.sectionInset.bottom - headerRect.height
//重点思考,在组头已经到达组尾,将要消失的情况下
headerRect.origin.y = min(finialHeaderY, headerMissingY)
attributes.frame = headerRect
attributes.zIndex = 7
//确定正在悬浮的header
if headerRect.minY == currentOffset || headerRect.minY == headerMissingY {
attributes.alpha = 0.8
}else {
attributes.alpha = 1
}
}
}
return superArray
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
网友评论