Last active
May 12, 2020 03:40
-
-
Save WenchaoD/06740053c8c0ddd3dc70 to your computer and use it in GitHub Desktop.
Subclass UICollectionViewFlowLayout to build a tag layout, and make UICollectionView scrolling smonthly while it holds dozens of cells with round corner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// TagCollectionViewCell.h | |
// | |
// Created by DingWenchao on 7/14/15. | |
// Copyright (c) 2015 demo. All rights reserved. | |
// | |
#import <UIKit/UIKit.h> | |
@interface TagCollectionViewCell : UICollectionViewCell | |
@property (weak, nonatomic) IBOutlet UILabel *textLabel; | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "TagCollectionViewCell.h" | |
@implementation TagCollectionViewCell | |
// Trick about round corner. If you set _textLabel.layer.cornerRadius = [], | |
// the scrolling speed of collectionView would suck. | |
- (void)awakeFromNib | |
{ | |
_textLabel.backgroundColor = [UIColor clearColor]; | |
_textLabel.layer.cornerRadius = 5; | |
// Huge change in performance by explicitly setting the below (even though default is supposedly NO) | |
_textLabel.layer.masksToBounds = NO; | |
// Performance improvement here depends on the size of your view | |
_textLabel.layer.shouldRasterize = YES; | |
_textLabel.layer.backgroundColor = _invert ? kRedTagColor.CGColor : kGreyTagColor.CGColor; | |
_textLabel.layer.rasterizationScale = [UIScreen mainScreen].scale; | |
} | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <UIKist/UIKit.h> | |
@interface TagFlowLayout : UICollectionViewFlowLayout | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "TagFlowLayout.h" | |
const NSInteger kMaxCellSpacing = 10; | |
@implementation TagFlowLayout | |
- (instancetype)init | |
{ | |
self = [super init]; | |
if (self) { | |
self.scrollDirection = UICollectionViewScrollDirectionVertical; | |
self.minimumInteritemSpacing = kMaxCellSpacing; | |
self.minimumLineSpacing = kMaxCellSpacing; | |
} | |
return self; | |
} | |
- (instancetype)initWithCoder:(NSCoder *)coder | |
{ | |
self = [super initWithCoder:coder]; | |
if (self) { | |
self.scrollDirection = UICollectionViewScrollDirectionVertical; | |
self.minimumInteritemSpacing = kMaxCellSpacing; | |
self.minimumLineSpacing = kMaxCellSpacing; | |
} | |
return self; | |
} | |
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect | |
{ | |
NSArray* attributesToReturn = [super layoutAttributesForElementsInRect:rect]; | |
for (UICollectionViewLayoutAttributes* attributes in attributesToReturn) { | |
if (nil == attributes.representedElementKind) { | |
NSIndexPath* indexPath = attributes.indexPath; | |
attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame; | |
} | |
} | |
return attributesToReturn; | |
} | |
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath | |
{ | |
UICollectionViewLayoutAttributes* currentItemAttributes = | |
[super layoutAttributesForItemAtIndexPath:indexPath]; | |
UIEdgeInsets sectionInset = [(UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout sectionInset]; | |
if (indexPath.item == 0) { // first item of section | |
CGRect frame = currentItemAttributes.frame; | |
frame.origin.x = sectionInset.left; // first item of the section should always be left aligned | |
currentItemAttributes.frame = frame; | |
return currentItemAttributes; | |
} | |
NSIndexPath* previousIndexPath = [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section]; | |
CGRect previousFrame = [self layoutAttributesForItemAtIndexPath:previousIndexPath].frame; | |
CGFloat previousFrameRightPoint = previousFrame.origin.x + previousFrame.size.width + kMaxCellSpacing; | |
CGRect currentFrame = currentItemAttributes.frame; | |
CGRect strecthedCurrentFrame = CGRectMake(0, | |
currentFrame.origin.y, | |
self.collectionView.frame.size.width, | |
currentFrame.size.height); | |
if (!CGRectIntersectsRect(previousFrame, strecthedCurrentFrame)) { // if current item is the first item on the line | |
// the approach here is to take the current frame, left align it to the edge of the view | |
// then stretch it the width of the collection view, if it intersects with the previous frame then that means it | |
// is on the same line, otherwise it is on it's own new line | |
CGRect frame = currentItemAttributes.frame; | |
frame.origin.x = sectionInset.left; // first item on the line should always be left aligned | |
currentItemAttributes.frame = frame; | |
return currentItemAttributes; | |
} | |
CGRect frame = currentItemAttributes.frame; | |
frame.origin.x = previousFrameRightPoint; | |
currentItemAttributes.frame = frame; | |
return currentItemAttributes; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment