簡體   English   中英

UICollectionView 中只有一個粘性標題

[英]Only one sticky header in UICollectionView

我正在嘗試在UICollectionView實現單個粘性標題。

我的粘性標題行為與您可以在UITableView看到的通常行為略有不同。 我在集合視圖中有 3 個標題,我只希望其中一個是粘性的,並在滾動內容時粘在頂部。

我的代碼運行良好。 但是,當我向下滾動時,粘性標題在某些時候突然消失了。 向后滾動會使標題再次出現。 我究竟做錯了什么?

我正在附加我的自定義布局的實現。 它是UICollectionViewFlowLayout的子類。

@implementation CustomFlowLayout


- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSMutableArray *attributes = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
    CGPoint const contentOffset = self.collectionView.contentOffset;

    for (UICollectionViewLayoutAttributes *layoutAttributes in attributes)
    {
        // Adjust the sticky header frame.
        if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader] &&
            layoutAttributes.indexPath.section == SectionWithStickyHeadeIndex)
        {
            NSInteger numberOfItemsInSection = [self.collectionView numberOfItemsInSection:SectionWithStickyHeadeIndex];
            NSIndexPath *firstObjectIndexPath = [NSIndexPath indexPathForItem:0
                                                                    inSection:SectionWithStickyHeadeIndex];
            UICollectionViewLayoutAttributes *firstObjectAttrs;

            if (numberOfItemsInSection > 0)
            {
                firstObjectAttrs = [self layoutAttributesForItemAtIndexPath:firstObjectIndexPath];
            }
            else
            {
                firstObjectAttrs = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader
                                                                        atIndexPath:firstObjectIndexPath];
            }

            CGPoint origin = layoutAttributes.frame.origin;

            // Adjust the header origin so it sticks to the top.
            origin.y = MAX(contentOffset.y + self.collectionView.contentInset.top,
                           CGRectGetMinY(firstObjectAttrs.frame) - CGRectGetHeight(layoutAttributes.frame));

            layoutAttributes.zIndex = CGFLOAT_MAX;
            layoutAttributes.frame = (CGRect)
            {
                .origin = origin,
                .size = layoutAttributes.frame.size
            };

            break;
        }
    }

    return attributes;
}


- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBound
{
    return YES;
}


@end

我不是 100% 確定這一點,但看起來一旦你向下滾動到足夠遠,標題的原始位置不再位於rect參數內。 這導致標題的布局屬性未包含在您在for循環中迭代的attributes數組中,從而導致布局位置不再調整到屏幕頂部的“粘性”位置。

嘗試在for循環之前添加這些行for以將粘性標題的布局屬性添加到attributes數組(如果它們尚未存在):

 NSIndexPath *stickyHeaderIndexPath = [NSIndexPath indexPathForItem:0 inSection:SectionWithStickyHeaderIndex]; UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:stickyHeaderIndexPath]; if (![attributes containsObject:layoutAttributes]) { [attributes addObject:layoutAttributes]; }

Swift 5 中的答案

let headerIndexPath = IndexPath(item: 0, section: 0)
if let headerAttributes = layoutAttributesForSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, at: headerIndexPath) {
    if !attributes.contains(headerAttributes) {
        attributes.append(headerAttributes)
    }
}

感謝@BrendanCain

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM