Reputation: 1009
Trying to add a horizontal Scrolling UICollectionView of times. The problem is after a bunch of cells, it's like the next ones are loading late. I have to frequently scroll all the way over the screen until the next group of cell will load. In the screen shot, the times 2:30PM & 3:00PM should already be visible.
View Controller
GHTMeetingTimesCollectionViewFlowLayout *timesFlowLayout = [[GHTMeetingTimesCollectionViewFlowLayout alloc] init];
timesFlowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
timesFlowLayout.itemSize = CGSizeMake(kIconCellItemWidth, kIconCollectionHeight);
self.timesSelectCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:timesFlowLayout];
self.timesSelectCollectionView.translatesAutoresizingMaskIntoConstraints = NO;
self.timesSelectCollectionView.allowsMultipleSelection = YES;
self.timesSelectCollectionView.showsHorizontalScrollIndicator = NO;
self.timesSelectCollectionView.backgroundColor = [UIColor clearColor];
self.timesSelectCollectionView.delegate = self;
self.timesSelectCollectionView.dataSource = self;
[self.contentView addSubview:self.timesSelectCollectionView];
[self.timesSelectCollectionView registerClass:[GHTMeetingTimeCollectionViewCell class] forCellWithReuseIdentifier:kMeetingTimeCellIdentifier];
GHTMeetingTimesCollectionViewFlowLayout
@implementation GHTMeetingTimesCollectionViewFlowLayout
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray* arr = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes* atts in arr) {
if (nil == atts.representedElementKind) {
NSIndexPath* attsPath = atts.indexPath;
atts.frame = [self layoutAttributesForItemAtIndexPath:attsPath].frame;
}
}
return arr;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes* atts = [super layoutAttributesForItemAtIndexPath:indexPath];
CGRect adjustedFrame = atts.frame;
adjustedFrame.origin.x = indexPath.row*kIconCellItemWidth;
adjustedFrame.size.width = kIconCellItemWidth;
adjustedFrame.size.height = kIconCollectionHeight;
atts.frame = adjustedFrame;
return atts;
}
CollectionView Cell Class
@implementation GHTMeetingTimeCollectionViewCell
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
self.highlightColor = [UIColor lightBlue];
self.timeLabel = [[UILabel alloc] init];
self.timeLabel.layer.cornerRadius = 3;
self.timeLabel.clipsToBounds = YES;
self.timeLabel.font = [UIFont fontWithName:GFFontStandard size:14];
self.timeLabel.textColor = [UIColor lightBlue];
self.timeLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.timeLabel.textAlignment = NSTextAlignmentCenter;
self.timeLabel.backgroundColor = [UIColor clearColor];
[self.contentView addSubview:self.timeLabel];
[NSLayoutConstraint sidesOfChild:self.timeLabel toSidesOfParent:self.contentView margin:8];
[NSLayoutConstraint centerYOfChild:self.timeLabel toCenterYOfParent:self.contentView];
}
return self;
}
-(void)setTimeDisplay:(NSString *)time {
self.timeLabel.text = time;
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
self.timeLabel.backgroundColor = selected ? self.highlightColor : [UIColor clearColor];
self.timeLabel.textColor = selected ? [UIColor whiteColor] : self.highlightColor;
}
- (void)setHighlightColor:(UIColor *)highlightColor {
_highlightColor = highlightColor;
self.timeLabel.backgroundColor = self.isSelected ? _highlightColor : [UIColor clearColor];
self.timeLabel.textColor = self.isSelected ? [UIColor whiteColor] : _highlightColor;
}
Delegate method
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
GHTMeetingTimeCollectionViewCell *cell = [self.timesSelectCollectionView dequeueReusableCellWithReuseIdentifier:kMeetingTimeCellIdentifier forIndexPath:indexPath];
NSDate *date = [self.times objectAtIndex:indexPath.row];
[cell setTimeDisplay:[self.timeOnlyFormatter stringFromDate:date]];
if (self.existing) {
[cell setHighlightColor:[UIColor lightGrayColor]];
}
return cell;
}
Upvotes: 0
Views: 742
Reputation: 1122
Try it that way :
@interface GHTMeetingTimesCollectionViewFlowLayout ()
@property (nonatomic, strong) NSMutableDictionary *layoutInfo;
@end
@implementation GHTMeetingTimesCollectionViewFlowLayout
- (NSDictionary *)layoutInfo
{
if (!_layoutInfo)
{
_layoutInfo = [NSMutableDictionary dictionary];
}
return _layoutInfo;
}
- (void)prepareLayout
{
NSInteger sectionCount = [self.collectionView numberOfSections];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
for (NSInteger section = 0; section < sectionCount; section++) {
NSInteger itemCount = [self.collectionView numberOfItemsInSection:section];
for (NSInteger item = 0; item < itemCount; item++) {
indexPath = [NSIndexPath indexPathForItem:item inSection:section];
UICollectionViewLayoutAttributes *atts = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
CGRect adjustedFrame = atts.frame;
adjustedFrame.origin.x = indexPath.row*kIconCellItemWidth;
adjustedFrame.size.width = kIconCellItemWidth;
adjustedFrame.size.height = kIconCollectionHeight;
atts.frame = adjustedFrame;
self.layoutInfo[indexPath] = atts;
}
}
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *allAttributes = [NSMutableArray arrayWithCapacity:self.layoutInfo.count];
[self.layoutInfo enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath, UICollectionViewLayoutAttributes *attributes, BOOL *innerStop)
{
if (CGRectIntersectsRect(rect, attributes.frame)) {
[allAttributes addObject:attributes];
}
}];
return allAttributes;
}
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
return self.layoutInfo[indexPath];
}
@end
PS : I just wrote that, didn't test it. I hope it doesn't contain any error. But it any case, it's the way you should handle custom flow layouts.
Upvotes: 1