未使用自定义UICollectionViewLayout调用cellForItemAtIndexPath

时间:2018-04-07 23:31:53

标签: ios uicollectionview uicollectionviewlayout

这是我初始化collectionView:

的方法
[] <<<< Async >>>> playerasync_runAsynchronousCommandOnQueue: Command 3 returned -12784; this async error will be discarded

比我有以下代表方法:

self.collectionView = [[UICollectionView alloc]initWithFrame:self.frame collectionViewLayout:[[customLayout alloc]init]];
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
//[self.collectionView setAlwaysBounceVertical:YES];
[self.collectionView setBackgroundColor:[UIColor blueColor]];
self.collectionView.decelerationRate = UIScrollViewDecelerationRateFast;
UINib *nibf = [UINib nibWithNibName:@"inviteUserCell" bundle:nil];
[self.collectionView registerNib:nibf forCellWithReuseIdentifier:@"user"];
[self addSubview:self.collectionView];

在我的日志中,我得到 - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ NSLog(@"sections 1"); return 1; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ NSLog(@"items 40"); return 40; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ inviteUserCell *cell = (inviteUserCell *) [collectionView dequeueReusableCellWithReuseIdentifier:@"user" forIndexPath:indexPath]; [cell setBackgroundColor:[UIColor whiteColor]]; NSLog(@"CELL: %@", cell); return cell; } sections 1,但我没有items 40。对于我的CELL: %@的子类,我有以下方法。

UICollectionViewLayout

我不确定我没有打电话或设置会让 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{ return true; } - (CGSize)collectionViewContentSize{ CGSize size = CGSizeMake(self.collectionView.frame.size.width, self.collectionView.frame.size.height); return size; } - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{ NSArray *attributesInRect = [super layoutAttributesForElementsInRect:rect]; for (UICollectionViewLayoutAttributes *cellAttributes in attributesInRect) { // [self modifyLayoutAttributes:cellAttributes]; cellAttributes.size = CGSizeMake(10, 10); cellAttributes.center = CGPointMake(100, 100); } return attributesInRect; } - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{ UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForItemAtIndexPath:indexPath]; // [self modifyLayoutAttributes:attributes]; attributes.size = CGSizeMake(10, 10); attributes.center = CGPointMake(100, 100); NSLog(@"Attr: %@", attributes); // this is null return attributes; } 被调用。

布局 所需的布局是50x50网格,垂直和放大水平滚动。从cellForItemAtIndexPath左右阅读只能进行垂直或水平滚动。所以我继承了UICollectionViewFlowLayout

1 个答案:

答案 0 :(得分:0)

一些观察结果:

  1. 关键问题是layoutAttributesForElementsInRect应该返回特定rect中可见的所有单元格的布局属性数组。如果不返回属性对象数组,每个可见单元格对应一个属性对象,则不会要求cellForItemAt生成任何单元格。

    现在,您将如何针对特定布局执行此操作可能会有所不同,但例如,这会找到与rect相交的所有内容,为每个内容调用layoutAttributesForItemAtIndexPath并附加它们到阵列。

  2. 您的layoutAttributesForItemAtIndexPath指定所有单元格的中心位于集合视图中的100,100,并且大小为10,10。简而言之,您指定它们都处于完全相同的位置,彼此重叠。这有点好奇。通常,每个单元格都有一些唯一的center

    如果你想要它们在50 x 50网格中,你可以这样做:

    //  CustomLayout.m
    
    #import "CustomLayout.h"
    
    static const CGSize    kCellSize    = { 70, 30 };  // make whatever size you want
    static const CGFloat   kCellSpacing = 5;
    static const NSInteger kCellsPerRow = 50;
    
    @implementation CustomLayout
    
    - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
        return true;
    }
    
    - (CGSize)collectionViewContentSize {
        NSInteger count = [self.collectionView numberOfItemsInSection:0];
        if (count == 0) return CGSizeZero;
    
        NSInteger numberOfColumns = MIN(kCellsPerRow, count);
        NSInteger numberOfRows = (count - 1) % kCellsPerRow + 1;
        return CGSizeMake(numberOfColumns * (kCellSize.width + kCellSpacing) + kCellSpacing,
                          numberOfRows * (kCellSize.height + kCellSpacing) + kCellSpacing);
    }
    
    - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
        NSMutableArray <UICollectionViewLayoutAttributes *> *attributes = [NSMutableArray array];
    
        NSInteger count = [self.collectionView numberOfItemsInSection:0];
        NSInteger numberOfRows = (count - 1) % kCellsPerRow + 1;
    
        NSInteger startColumn = MAX(0, floorf(rect.origin.x / (kCellSize.width + kCellSpacing)));
        NSInteger endColumn = MIN(kCellsPerRow, ceilf((rect.origin.x + rect.size.width) / (kCellSize.width + kCellSpacing)));
    
        NSInteger startRow = MAX(0, floorf(rect.origin.y / (kCellSize.height + kCellSpacing)));
        NSInteger endRow = MIN(numberOfRows, ceilf((rect.origin.y + rect.size.height) / (kCellSize.height + kCellSpacing)));
    
        for (NSInteger row = startRow; row < endRow; row++) {
            for (NSInteger column = startColumn; column < endColumn; column++) {
                NSInteger index = row * kCellsPerRow + column;
                if (index < count) {
                    [attributes addObject:[self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]]];
                }
            }
        }
    
        return attributes;
    }
    
    - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
        UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    
        NSInteger column = indexPath.item % kCellsPerRow;
        NSInteger row = indexPath.item / kCellsPerRow;
    
        attributes.size = kCellSize;
        attributes.center = CGPointMake(column * (kCellSize.width  + kCellSpacing) + kCellSpacing + kCellSize.width / 2,
                                        row    * (kCellSize.height + kCellSpacing) + kCellSpacing + kCellSize.height / 2);
    
        return attributes;
    }
    
    @end
    

    显然,如果你想要一个50 x 50的网格,那么你可能希望单元格的数量为2,500,而不是40。

  3. 我确信为简洁起见省略了它,但您的代码段并未演示集合视图collectionViewLayout的设置。

  4. 无论如何,上面的内容呈现了以下集合视图:

    enter image description here

    现在,我让我的细胞足够大,所以我可以在那里放一个标签并显示细胞的indexPath.item,但是可以制作任何你想要的尺寸。