- 经过查阅资料,最终实现效果
- 实现思路
- import
- import
- import “TFCollectionReusableView.h”
- import “TFCollectionViewLayoutAttributes.h”
- import “TFSectionDecorationConfig.h”
- import
- import “TFCollectionViewLayout.h”
- import “TFCollectionViewLayoutAttributes.h”
- import “TFCollectionReusableView.h”
- import “TFSectionDecorationConfig.h”
- import “ViewController.h”
- import “TFCollectionReusableHeaderView.h”
- import “TFCollectionViewLayout.h”
- import “TFSectionDecorationConfig.h”
- define kGGRandomColor [UIColor colorWithRed:random()%256/255.0 green:random()%256/255.0 blue:random()%256/255.0 alpha:1.0]
- pragma mark - UICollectionViewDataSource
- pragma mark - TFCollectionViewLayoutDelegate
经过查阅资料,最终实现效果
实现的原理如下:
- 自定义并注册复用视图 ``` @property(class, nonatomic, readonly) Class layoutAttributesClass; // override this method to provide a custom class to be used when instantiating instances of UICollectionViewLayoutAttributes
- (void)registerClass:(nullable Class)viewClass forDecorationViewOfKind:(NSString *)elementKind; ```
- 在layoutAttributesForElementsInRect方法中添加自定义的UICollectionViewLayoutAttributes,并设置LayoutAttributes的Frame(Frame的计算方式可以按照自己的需求做修改)
注意创建时需要使用自定义的UICollectionViewLayoutAttributes调用如下的方法以使其显示时使用自定义的UICollectionReusableView
+ (instancetype)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind withIndexPath:(NSIndexPath *)indexPath;
其实是可以对每一个item进行背景色处理的,主需按照需求在**layoutAttributesForElementsInRect方法中添加对应的**LayoutAttributes就可以了
实现思路
NS_ASSUME_NONNULL_BEGIN @class TFSectionDecorationConfig; @interface TFCollectionViewLayoutAttributes : UICollectionViewLayoutAttributes @property (nonatomic, strong) TFSectionDecorationConfig *decorationConfig; @end
NS_ASSUME_NONNULL_END
```
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface TFSectionDecorationConfig : NSObject
/// 参考Section的inset,在这里可以做适当的修改
@property (nonatomic, assign) UIEdgeInsets inset;
/// 背景色
@property (nonatomic, strong) UIColor *color;
/// 圆角
@property (nonatomic, assign) CGFloat cornerRadius;
@end
NS_ASSUME_NONNULL_END
NS_ASSUME_NONNULL_BEGIN
@interface TFCollectionReusableView : UICollectionReusableView
@end
NS_ASSUME_NONNULL_END
import “TFCollectionReusableView.h”
import “TFCollectionViewLayoutAttributes.h”
import “TFSectionDecorationConfig.h”
@implementation TFCollectionReusableView
(void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes { [super applyLayoutAttributes:layoutAttributes];
TFCollectionViewLayoutAttributes ecLayoutAttributes = (TFCollectionViewLayoutAttributes)layoutAttributes; TFSectionDecorationConfig *config = ecLayoutAttributes.decorationConfig; if (config == nil) {
self.backgroundColor = [UIColor clearColor];
return;
} self.backgroundColor = config.color; self.layer.cornerRadius = config.cornerRadius; self.layer.masksToBounds = YES; }
@end
3. 自定义UICollectionViewFlowLayout
1. 替换为自定义的UICollectionViewLayoutAttributes
1. 注册自定义的DecorationView
1. 在layoutAttributesForElementsInRect方法中,计算并添加自定义的UICollectionViewLayoutAttributes
import
NS_ASSUME_NONNULL_BEGIN
@class TFSectionDecorationConfig;
@class TFCollectionViewLayout;
@protocol TFCollectionViewLayoutDelegate
/// 返回分组背景视图配置 /// @param layout layout description /// @param section section description
- (TFSectionDecorationConfig _Nullable)tf_Layout:(TFCollectionViewLayout )layout decorationConfigForSectionAtIndex:(NSInteger)section;
@end
@interface TFCollectionViewLayout : UICollectionViewFlowLayout
@property (nonatomic, weak) id
@end
NS_ASSUME_NONNULL_END
import “TFCollectionViewLayout.h”
import “TFCollectionViewLayoutAttributes.h”
import “TFCollectionReusableView.h”
import “TFSectionDecorationConfig.h”
static NSString *TFSectionDecorationReuseID = @”SectionBg”;
@implementation TFCollectionViewLayout
/// 替换为自定义的LayoutAttributes类
- (Class)layoutAttributesClass { return [TFCollectionViewLayoutAttributes class]; }
/// 注册自定义的ReusableView,用于分组背景色显示
- (void)prepareLayout { [super prepareLayout]; [self registerClass:[TFCollectionReusableView class] forDecorationViewOfKind:TFSectionDecorationReuseID]; }
(NSArray )layoutAttributesForElementsInRect:(CGRect)rect { NSArray attributes = [super layoutAttributesForElementsInRect:rect];
NSMutableArray *allAttributes = [NSMutableArray arrayWithArray:attributes];
NSMutableArray *sectionAttributes = [NSMutableArray array];
NSInteger sections = self.collectionView.numberOfSections;
for (NSInteger section = 0; section<sections; section++) {
TFSectionDecorationConfig *config;
if (self.delegate && [self.delegate respondsToSelector:@selector(tf_Layout:decorationConfigForSectionAtIndex:)]) {
config = [self.delegate tf_Layout:self decorationConfigForSectionAtIndex:section];
}else{
continue;
}
NSInteger number = [self.collectionView numberOfItemsInSection:section];
UIEdgeInsets insets = config.inset;
if(number > 0){
NSIndexPath *firstIndex = [NSIndexPath indexPathForRow:0 inSection:section];
UICollectionViewLayoutAttributes *attribute = [self layoutAttributesForItemAtIndexPath:firstIndex];
CGRect frame = attribute.frame;
CGFloat minX = frame.origin.x;
CGFloat minY = frame.origin.y;
CGFloat maxX = CGRectGetMaxX(frame);
CGFloat maxY = CGRectGetMaxY(frame);
for (NSInteger row = 1; row<number; row++) {
attribute = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:row inSection:section]];
if (attribute.frame.origin.x < minX ) {
minX = attribute.frame.origin.x;
}
if (attribute.frame.origin.y < minY ) {
minY = attribute.frame.origin.y;
}
if (CGRectGetMaxX(attribute.frame) > maxX ) {
maxX = CGRectGetMaxX(attribute.frame);
}
if (CGRectGetMaxY(attribute.frame) > maxY ) {
maxY = CGRectGetMaxY(attribute.frame);
}
}
frame = CGRectMake(minX, minY, maxX - minX, maxY - minY);
TFCollectionViewLayoutAttributes *decorationAttributes =
[TFCollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:TFSectionDecorationReuseID
withIndexPath:attribute.indexPath];
decorationAttributes.decorationConfig = config;
CGFloat x = frame.origin.x - insets.left;
CGFloat y = frame.origin.y - insets.top;
CGFloat w = frame.size.width + insets.left + insets.right;
CGFloat h = frame.size.height + insets.top + insets.bottom;
decorationAttributes.frame = CGRectMake(x, y, w , h);
decorationAttributes.zIndex = attribute.zIndex-1;
[sectionAttributes addObject:decorationAttributes];
}
}
[allAttributes addObjectsFromArray:sectionAttributes];
return allAttributes;
} @end
- Demo效果代码
import “ViewController.h”
import “TFCollectionReusableHeaderView.h”
import “TFCollectionViewLayout.h”
import “TFSectionDecorationConfig.h”
define kGGRandomColor [UIColor colorWithRed:random()%256/255.0 green:random()%256/255.0 blue:random()%256/255.0 alpha:1.0]
@interface ViewController ()
@implementation ViewController
(void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.collectionView];
UIButton *refreshBtn = [UIButton new]; [self.view addSubview:refreshBtn]; [refreshBtn setTitle:@” 刷新 “ forState:UIControlStateNormal]; [refreshBtn addTarget:self action:@selector(btnDidClicked:) forControlEvents:UIControlEventTouchUpInside]; refreshBtn.frame = CGRectMake(0, 100, 50, 50);
}
- (void)btnDidClicked:(UIButton *)sender{ [self.collectionView reloadData]; }
(UICollectionView *)collectionView{ if (!_collectionView) {
TFCollectionViewLayout *flowLayout = [[TFCollectionViewLayout alloc] init];
flowLayout.delegate = self;
// UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.minimumLineSpacing = 5;
UICollectionView *view = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:flowLayout];
view.dataSource = self;
view.delegate = self;
view.backgroundColor = [UIColor whiteColor];
[view registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"UICollectionViewCell"];
[view registerClass:[TFCollectionReusableHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];
_collectionView = view;
} return _collectionView; }
pragma mark - UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return 5; }
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ return 10; }
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (__kindof UICollectionViewCell )collectionView:(UICollectionView )collectionView cellForItemAtIndexPath:(NSIndexPath )indexPath{ UICollectionViewCell cell = [collectionView dequeueReusableCellWithReuseIdentifier:@”UICollectionViewCell” forIndexPath:indexPath]; cell.backgroundColor = [UIColor systemPinkColor]; return cell; }
(UICollectionReusableView )collectionView:(UICollectionView )collectionView viewForSupplementaryElementOfKind:(NSString )kind atIndexPath:(NSIndexPath )indexPath{ TFCollectionReusableHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@”header” forIndexPath:indexPath]; headerView.backgroundColor = [UIColor darkGrayColor];
return headerView; }
(CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout )collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section{
CGSize size = collectionView.bounds.size; return CGSizeMake(size.width, 20); }
(CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout )collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath )indexPath{ CGSize itemSize = CGSizeMake(100, 100 + indexPath.row 20);
return itemSize; }
(UIEdgeInsets)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout )collectionViewLayout insetForSectionAtIndex:(NSInteger)section{ if (section < 2) {
return UIEdgeInsetsMake(0, 0, 0, 0);
} return UIEdgeInsetsMake(10 + 5 section, 10, 20, section 4 + 5); }
pragma mark - TFCollectionViewLayoutDelegate
- (TFSectionDecorationConfig _Nullable)tf_Layout:(TFCollectionViewLayout )layout decorationConfigForSectionAtIndex:(NSInteger)section{
if (section == 0) {
} UIEdgeInsets sectionInset = [self collectionView:self.collectionView layout:layout insetForSectionAtIndex:section]; TFSectionDecorationConfig *config = [TFSectionDecorationConfig new]; config.color = kGGRandomColor; config.inset = UIEdgeInsetsMake(sectionInset.top, sectionInset.left - 5, sectionInset.bottom, sectionInset.right - 5); config.cornerRadius = 10; return config; }return nil;
@end
```