我们正在尝试使用自定义布局设置 UICollectionView。每个 CollectionViewCell 的内容将是一个图像。总体而言,将有数千张图像,并且在某个特定时间可以看到大约 140-150 张图像。在一个动作事件上,所有单元格的位置和大小都可能重新组织。目标是为当前使用 performBatchUpdates 方法的所有移动事件设置动画。这会导致所有内容都被动画化之前的巨大延迟时间。
到目前为止,我们发现内部方法 layoutAttributesForItemAtIndexPath 为每个单元格(总共数千个)调用。此外,调用 cellForItemAtIndexPath 方法的单元格比实际显示在屏幕上的单元格多。
有没有可能提高动画的性能?
默认的 UICollectionViewFlowLayout 并不能真正提供我们想要在应用程序中实现的那种设计。这是我们的一些代码:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
RPDataModel *dm = [RPDataModel sharedInstance]; //Singleton holding some global information
NSArray *plistArray = dm.plistArray; //Array containing the contents of the cells
NSDictionary *dic = plistArray[[indexPath item]];
RPCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CELL" forIndexPath:indexPath];
cell.label.text = [NSString stringWithFormat:@"%@",dic[@"name"]];
cell.layer.borderColor = nil;
cell.layer.borderWidth = 0.0f;
[cell loadAndSetImageInBackgroundWithLocalFilePath:dic[@"path"]]; //custom method realizing asynchronous loading of the image inside of each cell
return cell;
}
layoutAttributesForElementsInRect 遍历所有元素,为矩形内的所有元素设置 layoutAttributes。for 语句在第一个单元格超出矩形右下角定义的边界时中断:
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray* attributes = [NSMutableArray array];
RPDataModel *dm = [RPDataModel sharedInstance];
for (int i = 0; i < dm.cellCount; i++) {
CGRect cellRect = [self.rp getCell:i]; //self.rp = custom object offering methods to get information about cells; the getCell method returns the rect of a single cell
if (CGRectIntersectsRect(rect, cellRect)) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:[dm.relevanceArray[i][@"product"] intValue] inSection:0];
UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attribute.size = cellRect.size;
attribute.center = CGPointMake(cellRect.origin.x + attribute.size.width / 2, cellRect.origin.y + attribute.size.height / 2);
[attributes addObject:attribute];
} else if (cellRect.origin.x > rect.origin.x + rect.size.width && cellRect.origin.y > rect.origin.y + rect.size.height) {
break;
}
}
return attributes;
}
在布局更改时,无论 layoutAttributesForElementsInRect 中定义的单元格数量是否有限,结果都几乎相同。如果系统没有限制,系统要么获取其中所有单元格的布局属性,要么调用所有缺失单元格的 layoutAttributesForElementAtIndexPath 方法(如果它是有限的)。总体而言,每个单元格的属性都在以某种方式使用。
-(UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
RPDataModel *dm = [RPDataModel sharedInstance];
UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
CGRect cellRect = [self.rp getCell:[dm.indexDictionary[@(indexPath.item)] intValue]];
attribute.size = cellRect.size;
attribute.center = CGPointMake(cellRect.origin.x + attribute.size.width / 2, cellRect.origin.y + attribute.size.height / 2);
return attribute;
}