简体   繁体   中英

UICollectionView Horizontal Scrollling Delay loading cells

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;
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM