The iOS – UICollectionView DecorationView packs your items with a box

1. demand:

Display category items on the same page. Use a specific container view between categories to wrap all the elements under this category. Classify the head and tail to display the relevant data. Following chart:

The iOS - UICollectionView DecorationView packs your items with a box
2. option:
  1. Using UITableView or UICollectionView, a category is a cell or item, and each element in the category is drawn in each cell or item.
  2. Using UICollectionView, each element is a item, and this time you need to think of a way to package the corresponding item.

“1” is undoubtedly the most simple, but when a category of special elements, and the category of UI to display complex (such as a cell N which has multiple elements), because of the large cell will need a one-time rendering, including no display on the screen within the element, will cause the performance the problem.
so let’s talk about the implementation of the program “2”.

3. implementation:

Each category is header, section, footer, the upper and lower three layers, the next DecorationView.

The iOS - UICollectionView DecorationView packs your items with a box
The iOS - UICollectionView DecorationView packs your items with a box

Create a UICollectionView using the custom layout (inheritance 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 = 0 (UIEdgeInsetsMake), 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 [self.view addSubview:collectionView]; [UIColor = whiteColor]; 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] of any resources; / / Dispose 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:indexP Ath]; 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 - UICollectionViewDe Legate @end

Configure the DecorationView in layout and calculate the location.

#import "HVWLayout.h" #import "HVWDecorationView.h" @implementation HVWLayout (void) prepareLayout [self registerClass:[HVWDecorationView class] {[super prepareLayout]; forDecorationViewOfKind:@ decorationView;} - (UICollectionViewLayoutAttributes *) layoutAttributesForDecorationViewOfKind: (* NSString) elementKind atIndexPath: (NSIndexPath *) indexPath top: (CGFloat) top UICollectionViewLayoutAttributes [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:elementKind withIndexPath:indexPath] {*attrs = NSUInteger; numberOfItems = [self.collectionView numberOfItemsInSection:indexPath.section] int; itemsPerRow = 3; NSUInteger = rows (numberOfItems + itemsPerRow / itemsPerRow - 1); CGFloat CellHeight CGFloat = 80; cellSpace = 20; CGFloat headerHeigh CGFloat = 90; footerHeight = 70; CGFloat = headerHeigh + height + cellSpace * cellHeight * rows (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 * superAttrs [super layoutAttributesForElementsInRect:rect] {NSArray = NSMutableArray; *attrs = [NSMutableArray arrayWithArray:superAttrs]; for (UICollectionViewLayoutAttributes *attr in superAttrs) {if (attr.representedElementKind = = UICollectionElementKindSect IonHeader) {[attrs addObject:[self layoutAttributesForDecorationViewOfKind:@ atIndexPath:attr.indexPath top:attr.frame.origin.y]] "decorationView";}} / / NSLog (@ "%s", __func__); return attrs;}

In DecorationView, the rewrite method applyLayoutAttributes computes the elements in the layout view.

Note that the layout cannot be overridden by rewriting setFrame or layoutSubViews because the two methods are called only once in initialization, and reuse will not be called.

#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:@ _imageView.image = "BG"]; [image stretchableImageWithLeftCapWidth:image.size.width/2 topCapHeight:image.size.height/2]; [self addSubview:_imageView];} return self;} - (void) applyLayoutAttributes: (UICollectionViewLayoutAttributes * layoutAttribute) S {[super applyLayoutAttributes:layoutAttributes]; / / NSLog (@ "%s", __func__); _imageView.frame = CGRectMake (10, 10, layoutAttributes.frame.size.width - 20, layoutAttributes.frame.size.height - 20);}