集合视图,具有自定义布局,单元格在滚动时行为不端

Posted

技术标签:

【中文标题】集合视图,具有自定义布局,单元格在滚动时行为不端【英文标题】:Collection View,with custom layouts, cells misbehave on scrolling 【发布时间】:2013-06-03 14:00:32 【问题描述】:

我正在尝试使用 UICollectionView 创建自定义平铺布局。 一旦我运行我的应用程序,它就可以在模拟器中完美呈现。

但是当我滚动视图并将其恢复时,所有单元格的框架都发生了变化,并且单元格重叠,随机地留下空间。

过去 2 天我无法解决此问题。 这是我的自定义布局类中的代码。

-(void)prepareLayout
[self createCellSizeArray];//cellSizeArray holds cell sizes for all the cells(calculated statically) 
[self createAttributeArrayOfAll];//attributeArrayOfAll holds attributes for all the cells and also calculates their frames using cellSizeArray


-(CGSize)collectionViewContentSize
   return CGSizeMake(768, 1500);//The size is static to check for scrolling, is this creating problems?


-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
      UICollectionViewLayoutAttributes * layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
      return layoutAttributes;


-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
    NSMutableArray *attArray =[NSMutableArray array];
    for (NSInteger i =0; i< attributeArrayOfAll.count; i++) 
    UICollectionViewLayoutAttributes * attribute = (UICollectionViewLayoutAttributes*)[attributeArrayOfAll objectAtIndex:i];
    if(CGRectIntersectsRect(rect, attribute.frame))
        [attArray addObject:attribute];
    

return attArray;


-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
  return YES;

请帮忙,在此先感谢。

编辑: 在我的[self createAttributeArrayOfAll]; 我有这些代码行

CGRect frame = CGRectMake(_startNewRowPoint.x, _startNewRowPoint.y, cellSize.width, cellSize.height);
 UICollectionViewLayoutAttributes * attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
 attribute.alpha = 1.0;
 attribute.frame = frame;
 [attributeArrayOfAll addObject:attribute];

当我修改 layoutAttributesForItemAtIndexPath: 时,看起来像这样

-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
 UICollectionViewLayoutAttributes * layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
 layoutAttributes.frame = ((UICollectionViewLayoutAttributes*)[attributeArrayOfAll objectAtIndex:indexPath.item]).frame;
 return layoutAttributes;

此外,方法layoutAttributesForItemAtIndexPath: 永远不会被隐式调用。我什至试过这个:

-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
NSMutableArray *attArray =[NSMutableArray arrayWithCapacity:attributeArrayOfAll.count];
for (NSInteger i =0; i< attributeArrayOfAll.count; i++) 
    UICollectionViewLayoutAttributes * attribute = (UICollectionViewLayoutAttributes*)[attributeArrayOfAll objectAtIndex:i];
    if(CGRectIntersectsRect(rect, attribute.frame))
        [attArray insertObject:[self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]] atIndex:i];
    

return attArray;

但结果仍然是滚动时相同的扭曲单元格集。 我使用了 5 个单元格,第一次正确渲染时,在滚动时将其带回可见矩形,它会变形,如果我再次滚动并带回可见矩形,它会正确渲染。但是,当我使用大约 400 个单元格执行此操作时,一旦我滚动它就永远不会正确呈现。即使在重新加载集合视图时,单元格也会变形。请帮忙。

【问题讨论】:

【参考方案1】:

您的layoutAttributesForItemAtIndexPath: 方法在返回之前未设置layoutAttributes 对象的任何属性。需要设置frame(或centersize)。

【讨论】:

【参考方案2】:

所以终于设法解决了!在 cellForRow 中使用唯一的单元格标识符将每个单元格出列:

[self.summaryView registerClass:[BFSSummaryViewCell class] forCellWithReuseIdentifier:[NSString stringWithFormat:@"%@%d",CellIdentifier,indexPath.row]];
UICollectionViewCell *collectionCell = [collectionView dequeueReusableCellWithReuseIdentifier:[NSString stringWithFormat:@"%@%d",CellIdentifier,indexPath.row] forIndexPath:indexPath];

cellForRow 中的这两行代码对我有用,但是由于我的集合视图有大约 1000 个单元格,它大大增加了我的应用程序的大小。让我们希望苹果尽快修复这个错误。

【讨论】:

对不起,但这是解决此问题的糟糕方法。设置 UICollectionView 类的体系结构,以便您可以重用单元格。如果您对每个可能的单元格都有不同的单元格类别,那么您只是在为自己制造困难。尝试解决您遇到的实际问题,而不使用此 hack。 @buildsucceeded 我知道这是一个悲伤和糟糕的出路。但是我找到了一个可以解决这个问题的开放雷达,尽管几乎尝试了所有方法,但我别无选择。如果您可以分享更好的解决方案,我们将非常欢迎您。相信我,我的收藏视图在滚动时变得非常暴躁。我做噩梦了!!!! :) 看起来您正在尝试自己对单元格进行过多管理,即使没有每个单元格(不寒而栗)一个类的“解决方法”。你在哪里调用 cellForItemAtIndexPath 和出队?如果我是你,我会在一个全新的项目中重新开始,并确保在我开始覆盖你正在使用的任何方法之前,出队工作不会弄乱属性。 @buildsucceeded 上面的代码只显示了我的自定义布局的类。如果您想创建自己的布局,则需要覆盖上述方法。 cellForItemAtIndexPath: 在我的集合视图控制器类中实现,我在其中出队(无论如何,如果不在集合视图中出队,您将无法继续)。正如我所说,我为上述问题找到了一个开放的雷达,因此找到了这个粗略的解决方法。是 小区管理可以改进。但这不是这里的问题。

以上是关于集合视图,具有自定义布局,单元格在滚动时行为不端的主要内容,如果未能解决你的问题,请参考以下文章

用于 UITableView 的自定义 XIB 单元格在滚动时卡住/卡住

Swift 3 自定义单元格在滚动时更改

uitableview 自定义单元格在向下滚动 uitableview 时丢失其内容

UICollectionView 单元格在可见时不断重新加载

自定义 UITableViewCell 的布局何时完成?

自定义 UICollectionViewFlowLayout 问题