要么实现以下委托方法:
– collectionView:layout:sizeForItemAtIndexPath:
– collectionView:layout:insetForSectionAtIndex:
– collectionView:layout:minimumLineSpacingForSectionAtIndex:
– collectionView:layout:minimumInteritemSpacingForSectionAtIndex:
– collectionView:layout:referenceSizeForHeaderInSection:
– collectionView:layout:referenceSizeForFooterInSection:
在具有您的:cellForItemAtIndexPath
方法的视图控制器中(只需返回正确的值)。或者,您也可以直接在布局对象中设置这些值,而不是使用委托方法,例如[layout setItemSize:size];
.
使用这些方法中的任何一种都可以让您在代码中设置您的设置,而不是在 IB 中设置,因为它们在您设置自定义布局时会被删除。记住也要添加<UICollectionViewDelegateFlowLayout>
到您的 .h 文件中!
创建一个新的 Subclass UICollectionViewFlowLayout
,随意调用它,并确保 H 文件具有:
#import <UIKit/UIKit.h>
@interface YourSubclassNameHere : UICollectionViewFlowLayout
@end
在实现文件中确保它具有以下内容:
- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray *answer = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
UICollectionView * const cv = self.collectionView;
CGPoint const contentOffset = cv.contentOffset;
NSMutableIndexSet *missingSections = [NSMutableIndexSet indexSet];
for (UICollectionViewLayoutAttributes *layoutAttributes in answer) {
if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
[missingSections addIndex:layoutAttributes.indexPath.section];
}
}
for (UICollectionViewLayoutAttributes *layoutAttributes in answer) {
if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
[missingSections removeIndex:layoutAttributes.indexPath.section];
}
}
[missingSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx];
UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
[answer addObject:layoutAttributes];
}];
for (UICollectionViewLayoutAttributes *layoutAttributes in answer) {
if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
NSInteger section = layoutAttributes.indexPath.section;
NSInteger numberOfItemsInSection = [cv numberOfItemsInSection:section];
NSIndexPath *firstCellIndexPath = [NSIndexPath indexPathForItem:0 inSection:section];
NSIndexPath *lastCellIndexPath = [NSIndexPath indexPathForItem:MAX(0, (numberOfItemsInSection - 1)) inSection:section];
NSIndexPath *firstObjectIndexPath = [NSIndexPath indexPathForItem:0 inSection:section];
NSIndexPath *lastObjectIndexPath = [NSIndexPath indexPathForItem:MAX(0, (numberOfItemsInSection - 1)) inSection:section];
UICollectionViewLayoutAttributes *firstObjectAttrs;
UICollectionViewLayoutAttributes *lastObjectAttrs;
if (numberOfItemsInSection > 0) {
firstObjectAttrs = [self layoutAttributesForItemAtIndexPath:firstObjectIndexPath];
lastObjectAttrs = [self layoutAttributesForItemAtIndexPath:lastObjectIndexPath];
} else {
firstObjectAttrs = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader
atIndexPath:firstObjectIndexPath];
lastObjectAttrs = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter
atIndexPath:lastObjectIndexPath];
}
CGFloat headerHeight = CGRectGetHeight(layoutAttributes.frame);
CGPoint origin = layoutAttributes.frame.origin;
origin.y = MIN(
MAX(
contentOffset.y + cv.contentInset.top,
(CGRectGetMinY(firstObjectAttrs.frame) - headerHeight)
),
(CGRectGetMaxY(lastObjectAttrs.frame) - headerHeight)
);
layoutAttributes.zIndex = 1024;
layoutAttributes.frame = (CGRect){
.origin = origin,
.size = layoutAttributes.frame.size
};
}
}
return answer;
}
- (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBound {
return YES;
}
在 Interface Builder 中为 Flow Layout 选择“Custom”,选择您刚刚创建的“YourSubclassNameHere”类。跑!
(注意:上面的代码可能不尊重 contentInset.bottom 值,或者特别大或小的页脚对象,或者有 0 个对象但没有页脚的集合。)