1.需求:
在同一個頁面展示分類items槽驶,類別之間使用特定的“容器”視圖包裹此分類下的所有元素老虫,分類頭部和尾部要顯示相關數(shù)據(jù)。如下圖:
image
2.可選方案:
- 使用UITableView或者UICollectionView黍衙,一個分類就是一個cell或者item冕象, 每個cell或item內(nèi)再繪制類別下所有元素。
- 使用UICollectionView龟梦,每個元素都是一個item隐锭,這時候就需要想辦法,把相應的item給“包”起來计贰。
方案“1”無疑是最簡單的實現(xiàn)钦睡,但是如果當一個類別的元素特別多,而且類別需要顯示的UI特別復雜(例如一個cell里面有N多個元素)躁倒,就會因為這個大cell需要一次性繪制荞怒,包括沒有顯示在屏幕內(nèi)的元素,會造成性能問題秧秉。
所以我們來探討一下方案“2”的實現(xiàn)褐桌。
3. 實現(xiàn):
每個類別header、section象迎、footer上中下三層荧嵌,底下一個DecorationView。
image
image
創(chuàng)建一個UICollectionView砾淌,使用自定義的layout(繼承UICollectionViewFlowLayout)啦撮。
#import "ViewController.h"
#import "HVWLayout.h"
#import "HVWHeader.h"
#import "HVWFooter.h"
@interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor whiteColor];
self.automaticallyAdjustsScrollViewInsets = NO;
HVWLayout *layout = [[HVWLayout alloc] init];
layout.itemSize = CGSizeMake(80, 80);
layout.headerReferenceSize = CGSizeMake(self.view.bounds.size.width, 90);
layout.footerReferenceSize = CGSizeMake(self.view.bounds.size.width, 70);
layout.sectionInset = UIEdgeInsetsMake(0, 30, 0, 30);
layout.minimumLineSpacing = 20;
layout.minimumInteritemSpacing = ([UIScreen mainScreen].bounds.size.width - 80 * 3 - 60) / 2;
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
collectionView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:collectionView];
collectionView.dataSource = self;
collectionView.delegate = self;
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
[collectionView registerClass:[HVWHeader class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];
[collectionView registerClass:[HVWFooter class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"footer"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UICollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 10;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return section + 4;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor orangeColor];
return cell;
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
if (kind == UICollectionElementKindSectionHeader) {
return [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header" forIndexPath:indexPath];
} else if (kind == UICollectionElementKindSectionFooter) {
return [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"footer" forIndexPath:indexPath];
}
return nil;
}
#pragma mark - UICollectionViewDelegate
@end
在layout里面配置DecorationView,計算出位置汪厨。
#import "HVWLayout.h"
#import "HVWDecorationView.h"
@implementation HVWLayout
- (void)prepareLayout {
[super prepareLayout];
[self registerClass:[HVWDecorationView class] forDecorationViewOfKind:@"decorationView"];
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath top:(CGFloat)top {
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:elementKind withIndexPath:indexPath];
NSUInteger numberOfItems = [self.collectionView numberOfItemsInSection:indexPath.section];
int itemsPerRow = 3;
NSUInteger rows = (numberOfItems + itemsPerRow - 1) / itemsPerRow;
CGFloat cellHeight = 80;
CGFloat cellSpace = 20;
CGFloat headerHeigh = 90;
CGFloat footerHeight = 70;
CGFloat height = headerHeigh + cellHeight * rows + cellSpace * (rows - 1) + footerHeight;
attrs.frame = CGRectMake(0, top, [UIScreen mainScreen].bounds.size.width, height);
attrs.zIndex = -1;
// NSLog(@"%s", __func__);
return attrs;
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray *superAttrs = [super layoutAttributesForElementsInRect:rect];
NSMutableArray *attrs = [NSMutableArray arrayWithArray:superAttrs];
for (UICollectionViewLayoutAttributes *attr in superAttrs) {
if (attr.representedElementKind == UICollectionElementKindSectionHeader) {
[attrs addObject:[self layoutAttributesForDecorationViewOfKind:@"decorationView" atIndexPath:attr.indexPath top:attr.frame.origin.y]];
}
}
// NSLog(@"%s", __func__);
return attrs;
}
在DecorationView中赃春,重寫方法applyLayoutAttributes,重新計算布局view內(nèi)的元素劫乱。
注意不能靠重寫setFrame或者layoutSubViews來布局织中,因為這兩方法只在初始化的時候調(diào)用一次,重用就不會調(diào)用了衷戈。
#import "HVWDecorationView.h"
@interface HVWDecorationView()
@property(nonatomic, strong) UIImageView *imageView;
@end
@implementation HVWDecorationView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// self.backgroundColor = [UIColor grayColor];
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, frame.size.width - 20, frame.size.height - 20)];
UIImage *image = [UIImage imageNamed:@"bg"];
_imageView.image = [image stretchableImageWithLeftCapWidth:image.size.width/2 topCapHeight:image.size.height/2];
[self addSubview:_imageView];
}
return self;
}
- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
[super applyLayoutAttributes:layoutAttributes];
// NSLog(@"%s", __func__);
_imageView.frame = CGRectMake(10, 10, layoutAttributes.frame.size.width - 20, layoutAttributes.frame.size.height - 20);
}
作者:西蒙SIMON
鏈接:http://www.reibang.com/p/565dfb3c23d1
來源:簡書
簡書著作權歸作者所有抠璃,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權并注明出處。