2015-08-03 11 views
7

Bir koleksiyon görünümünün en üstte olduğu bir koleksiyon çoğaltmaya çalışıyorum, koleksiyon görünümünün ilk satırının üst kısmındaki bir başlık görünümü, ardından bir başlık bölümü görünümü (indexPath.section == 1 için), örtüşen veya altında gitmeden başlık görünümüne yapışır.UICollectionView Bölüm Üstbilgisi Çubuğa belirli bir Y

Başlığı yapışkan hale getirmek için özel bir düzen uygulamıyorum. Ancak, başlık görünümüne sadık kalamayım ('origin.y + height'dan sonra), koleksiyon görünümünün en üstüne yapışır. kaydırma önce

:

enter image description here

özel düzeni ile bağlantılı: Burada enter image description here

İdeal senaryo

İşte benim IB yapısı var

enter image description here

kaydırma sonra:

@implementation LLCollectionCustomFlowLayout 

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

- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect { 

    NSMutableArray *answer = [[super layoutAttributesForElementsInRect:rect] mutableCopy]; 

    NSMutableIndexSet *missingSections = [NSMutableIndexSet indexSet]; 
    for (NSUInteger idx=0; idx<[answer count]; idx++) { 
     UICollectionViewLayoutAttributes *layoutAttributes = answer[idx]; 

     if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) { 
      [missingSections addIndex:layoutAttributes.indexPath.section]; // remember that we need to layout header for this section 
     } 
     if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) { 
      [answer removeObjectAtIndex:idx]; // remove layout of header done by our super, we will do it right later 
      idx--; 
     } 
    } 

    // layout all headers needed for the rect using self code 
    [missingSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { 
     NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx]; 
     UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath]; 
     if (layoutAttributes != nil) { 
      [answer addObject:layoutAttributes]; 
     } 
    }]; 

    return answer; 
} 


- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 
    UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath]; 
    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) { 
     UICollectionView * const cv = self.collectionView; 
     CGPoint const contentOffset = cv.contentOffset; 
     CGPoint nextHeaderOrigin = CGPointMake(INFINITY, INFINITY); 

     if (indexPath.section+1 < [cv numberOfSections]) { 
      UICollectionViewLayoutAttributes *nextHeaderAttributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:indexPath.section+1]]; 
      nextHeaderOrigin = nextHeaderAttributes.frame.origin; 
     } 

     CGRect frame = attributes.frame; 
     if (self.scrollDirection == UICollectionViewScrollDirectionVertical) { 

      frame.origin.y = MIN(MAX(contentOffset.y, frame.origin.y), nextHeaderOrigin.y - CGRectGetHeight(frame)); 


     } 
     else { // UICollectionViewScrollDirectionHorizontal 
      frame.origin.x = MIN(MAX(contentOffset.x, frame.origin.x), nextHeaderOrigin.x - CGRectGetWidth(frame)); 
     } 
     attributes.zIndex = 1024; 
     attributes.frame = frame; 
    } 
    return attributes; 
} 

- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 
    UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath]; 
    return attributes; 
} 
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 
    UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath]; 
    return attributes; 
} 

@end 

cevap

3

:

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{ 

    if (section == 0) { 
     return UIEdgeInsetsMake(-kHEIGHT_TOP_VIEW, 0, 0, 0); 
    }else 
     return UIEdgeInsetsMake(0, 0, 0, 0); 

} 

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section 
{ 

     return CGSizeMake(self.collectionView.frame.size.width, -kHEIGHT_TOP_VIEW); 
} 

:

- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect { 

    NSMutableArray *answer = [[super layoutAttributesForElementsInRect:rect] mutableCopy]; 

    NSMutableIndexSet *missingSections = [NSMutableIndexSet indexSet]; 
    for (NSUInteger idx=0; idx<[answer count]; idx++) { 
     UICollectionViewLayoutAttributes *layoutAttributes = answer[idx]; 

     if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) { 
      [missingSections addIndex:layoutAttributes.indexPath.section]; // remember that we need to layout header for this section 
     } 
     if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) { 
      [answer removeObjectAtIndex:idx]; // remove layout of header done by our super, we will do it right later 
      idx--; 
     } 
    } 

    // layout all headers needed for the rect using self code 
    [missingSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { 
     NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx]; 
     UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath]; 
     if (layoutAttributes != nil) { 
      [answer addObject:layoutAttributes]; 
     } 

     if (idx == 1) { 
      NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; 
      UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath]; 
      if (layoutAttributes != nil) { 
       [answer addObject:layoutAttributes]; 
      } 
     } 
    }]; 

    return answer; 
} 

- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 
    UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath]; 
    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) { 
     UICollectionView * const cv = self.collectionView; 
     CGPoint const contentOffset = cv.contentOffset; 
     CGPoint previousHeaderOrigin = CGPointMake(INFINITY, INFINITY); 
     CGFloat previousSectionY = 0; 

     if (indexPath.section == 1) { 
      UICollectionViewLayoutAttributes *previousHeaderAttributes = [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; 
      previousSectionY = previousHeaderAttributes.frame.origin.y; 
     } 

     CGRect frame = attributes.frame; 
     if (self.scrollDirection == UICollectionViewScrollDirectionVertical) { 

      if (indexPath.section == 0) { 
       frame.origin.y = MAX(contentOffset.y, frame.origin.y); 
      }else{ 
      frame.origin.y = MAX(previousSectionY+frame.size.height, frame.origin.y); 
      } 
     } 
     else { // UICollectionViewScrollDirectionHorizontal 
      frame.origin.x = MIN(MAX(contentOffset.x, frame.origin.x), previousHeaderOrigin.x - CGRectGetWidth(frame)); 
     } 
     attributes.zIndex = 1024; 
     attributes.frame = frame; 
    } 
    return attributes; 
} 

Ayrıca dosyada ben CollectionView'ın sahip olduğu Daha iyi bir cevabınız varsa, bize bildirin, böylece sizi kabul edebilirim ve ödülünüzü ödüllendirebilirim.

4

mesele buradadır:

frame.origin.y = MIN(MAX(contentOffset.y, frame.origin.y), nextHeaderOrigin.y - CGRectGetHeight(frame)); 

İşte

enter image description here

kod bu Üstbilgi sonuncudur, nextHeaderOrigin = CGPointMake(INFINITY, INFINITY). Bu nedenle frame.origin.y, MAX(contentOffset.y, frame.origin.y) olacaktır ve koleksiyon görünümünün en üstüne yapışacaktır. Bir sonraki şekilde layoutAttributesForSupplementaryViewOfKind güncelleştirmek gerekir: bunu bir kabataslak bir şekilde çözdük

- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 
    UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath]; 
    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) { 
     // for the header in the section #0, we have "sticky" behaviour by default 
     if (indexPath.section == 0) { 
      return attributes; 
     } 
     CGPoint contentOffset = self.collectionView.contentOffset; 
     UICollectionViewLayoutAttributes *prevHeaderAttributes = [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:indexPath.section - 1]]; 
     CGFloat prevHeaderMaxY = CGRectGetMaxY(prevHeaderAttributes.frame); // The maximum Y value from the previous header should be the position we use to "stick" the current one 
     CGFloat prevHeaderMaxX = CGRectGetMaxX(prevHeaderAttributes.frame); 
     CGRect frame = attributes.frame; 
     if (self.scrollDirection == UICollectionViewScrollDirectionVertical) { 
      frame.origin.y = MAX(frame.origin.y, prevHeaderMaxY); 
     } 
     else { // UICollectionViewScrollDirectionHorizontal 
      frame.origin.x = MAX(frame.origin.x, prevHeaderMaxX); 
     } 
     attributes.frame = frame; 
    } 
    return attributes; 
} 
+0

Cevabınız için teşekkür ederiz. Yine de çalışmıyor. İki derleyici uyarısını düzelttikten sonra (prevHeaderMaxY ve prevHeaderMaxX, CGFloats olmalıdır), başlık artık üstte kalmaz. Bunun bir bölüm [0] üstbilgisinin yokluğundan kaynaklandığına inanıyorum. Nil olduğu gibi, yapıştırma noktasını bulamıyor. – jonypz

+0

İlk üstbilgiyi geri koydum ve hala çalışmıyor. Şimdi başlıklar artık yapışmıyor. – jonypz

+0

Kullanmaya çalışın UICollectionViewLayoutAttributes * prevHeaderAttributes = [self layoutAttributesFor ... 'yerine UICollectionViewLayoutAttributes * prevHeaderAttributes = [super ...'. Süper arama, önceki sürümün doğru özelliklerini döndürmez. başlık – sgl0v