Окончательное решение я нашел:
Используя этот макет пользовательского потока можно было зафиксировать этот липкий заголовок:
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))
Надеясь, что это полезно для других!
Update
Обновлено исправить аварии (спасибо Роберт Аткинс!) И некоторые обновления Swift 1,2
tvOS & IOS 9
tvOS и IOS 9 введены свойство sectionHeadersPinToVisibleBounds
, который может быть использован
Я получаю EXC_ARITHMETIC аварии на линии 'firstCellAttrs = ...', возможно, что-то связано с http://stackoverflow.com/questions/24616797/uicollectionviewflowlayout-subclass-crashes-accessing-array- за пределами границ? –
По-видимому, это не работает для меня: Xcode 6.1.1 и iOS 8 :-(Любые идеи? Могли бы вы провести повторный тест? Заголовок должен придерживаться вершины, как в https://github.com/jamztang/CSStickyHeaderFlowLayout right ? – blackjacx
Не работает для меня сбои здесь 'self.layoutAttributesForSupplementaryViewOfKind (UICollectionElementKindSectionFooter, atIndexPath: lastCellIndexPath))' –