我正在尝试创建一个粘性补充标题,该标题始终保持在顶部,并且不会响应滚动事件。到目前为止,我发现的解决方案仍然可以对快速滚动进行反应,并使用自定义flowLayout进行了修复,这也可能是解决我的问题的方法。
我想要这种方式的原因是该标头在其他地方使用并且应该可重用。我希望可以通过这种方式解决此问题,而不必创建单独的视图。
当我在Swift中进行此操作时,在Swift中有一个示例将是很棒的。
我发现的最终解决方案是:
使用此自定义流程布局可以修复此粘性标头:
class StickyHeaderCollectionViewFlowLayout: UICollectionViewFlowLayout { override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? { var superAttributes: [UICollectionViewLayoutAttributes]? = super.layoutAttributesForElementsInRect(rect) as? [UICollectionViewLayoutAttributes] if superAttributes == nil { // If superAttributes couldn't cast, return return super.layoutAttributesForElementsInRect(rect) } let contentOffset = collectionView!.contentOffset var missingSections = NSMutableIndexSet() for layoutAttributes in superAttributes! { if (layoutAttributes.representedElementCategory == .Cell) { if let indexPath = layoutAttributes.indexPath { missingSections.addIndex(layoutAttributes.indexPath.section) } } } for layoutAttributes in superAttributes! { if let representedElementKind = layoutAttributes.representedElementKind { if representedElementKind == UICollectionElementKindSectionHeader { if let indexPath = layoutAttributes.indexPath { missingSections.removeIndex(indexPath.section) } } } } missingSections.enumerateIndexesUsingBlock { idx, stop in let indexPath = NSIndexPath(forItem: 0, inSection: idx) if let layoutAttributes = self.layoutAttributesForSupplementaryViewOfKind(UICollectionElementKindSectionHeader, atIndexPath: indexPath) { superAttributes!.append(layoutAttributes) } } for layoutAttributes in superAttributes! { if let representedElementKind = layoutAttributes.representedElementKind { if representedElementKind == UICollectionElementKindSectionHeader { let section = layoutAttributes.indexPath!.section let numberOfItemsInSection = collectionView!.numberOfItemsInSection(section) let firstCellIndexPath = NSIndexPath(forItem: 0, inSection: section)! let lastCellIndexPath = NSIndexPath(forItem: max(0, (numberOfItemsInSection - 1)), inSection: section)! let (firstCellAttributes: UICollectionViewLayoutAttributes, lastCellAttributes: UICollectionViewLayoutAttributes) = { if (self.collectionView!.numberOfItemsInSection(section) > 0) { return ( self.layoutAttributesForItemAtIndexPath(firstCellIndexPath), self.layoutAttributesForItemAtIndexPath(lastCellIndexPath)) } else { return ( self.layoutAttributesForSupplementaryViewOfKind(UICollectionElementKindSectionHeader, atIndexPath: firstCellIndexPath), self.layoutAttributesForSupplementaryViewOfKind(UICollectionElementKindSectionFooter, atIndexPath: lastCellIndexPath)) } }() let headerHeight = CGRectGetHeight(layoutAttributes.frame) var origin = layoutAttributes.frame.origin origin.y = min(contentOffset.y, (CGRectGetMaxY(lastCellAttributes.frame) - headerHeight)) // Uncomment this line for normal behaviour: // origin.y = min(max(contentOffset.y, (CGRectGetMinY(firstCellAttributes.frame) - headerHeight)), (CGRectGetMaxY(lastCellAttributes.frame) - headerHeight)) layoutAttributes.zIndex = 1024 layoutAttributes.frame = CGRect(origin: origin, size: layoutAttributes.frame.size) } } } return superAttributes } override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool { return true } }
要创建标题像传统标题一样粘滞的布局,请更改以下行:
origin.y = min(contentOffset.y, (CGRectGetMaxY(lastCellAttrs.frame) - headerHeight))
到这行:
origin.y = min(max(contentOffset.y, (CGRectGetMinY(firstCellAttrs.frame) - headerHeight)), (CGRectGetMaxY(lastCellAttrs.frame) - headerHeight))
希望这对其他人有用!
更新资料
更新以修复崩溃(感谢Robert Atkins!)和对Swift 1.2的一些更新。
tvOS和iOS 9
tvOS和iOS 9引入了sectionHeadersPinToVisibleBounds可以使用的属性
sectionHeadersPinToVisibleBounds