具有自调整大小的单元格的UICollectionView在插入/移除动画期间调整单元格大小

时间:2015-06-29 13:51:46

标签: ios ios8 autolayout uicollectionview

我有一个带有UICollectionViewFlowLayout的简单UICollectionView,它使用autolayout来允许自定义单元格。在静态布局中,事情很有效,但是当我插入或删除单元格时,单元格会调整为估计的大小:

[self.collectionView performBatchUpdates:^{
    [self.collectionView insertItemsAtIndexPaths:@[indexPath]];
} completion:nil];

除了设置估计的大小,像这样:

layout.estimatedItemSize = CGSizeMake(88.0, 88.0);

我在集合视图中没有做任何奇特的事情。一切都是使用故事板设置的。

如何避免调整大小?我只针对iOS 8.0及以上版本,因此应该支持它。

example of the problem

4 个答案:

答案 0 :(得分:1)

我碰到了这个,我花了一段时间才弄清楚它恢复的大小是估计的大小。

我想我想出了一个解决方法:

  • 保留自定义单元格类的一个实例
  • 实施sizeForItemAtIndexPath,并使用该索引路径的数据配置该单元实例,然后询问其首选大小(systemLayoutFittingSize)。
  • 将此信息缓存在字典中以提高性能。

参见示例项目here

答案 1 :(得分:0)

一个直接的解决方案是实现UICollectionViewDelegateFlowLayout方法

 func collectionView(_ collectionView: UICollectionView, layoutcollectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
      // calculate string size here
}

插入或删除单元格后,请确保使布局无效,以便再次调用委托方法

collectionView.performBatchUpdates({ 
    // insert/delete items here
}) { (success: Bool) in
    collectionView.collectionViewLayout.invalidateLayout()
}

答案 2 :(得分:0)

  1. estimatedItemSize属性设置为适当的大小。

  2. 在您的自定义UICollectionView类覆盖下面的方法和缓存layoutAttributes的大小由super给出。

    -(UICollectionViewLayoutAttributes*)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
    {
        UICollectionViewLayoutAttributes * superAttr = [super preferredLayoutAttributesFittingAttributes:layoutAttributes];
       //Cache size which is returned by super (superAttr.frame.size) since super calculates the correct size for auto size cells.
        return superAttr;
    }
    
  3. 3.In sizeForItemAtIndexPath返回缓存大小(如果可用的其他估计大小。

    -(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
    {
        //return cached size if available else the estimated size
    }
    

答案 3 :(得分:0)

要避免细胞大小调整,请使用InvalidationContext

    let context = UICollectionViewFlowLayoutInvalidationContext()
    context.invalidateFlowLayoutAttributes = false
    collectionView.collectionViewLayout.invalidateLayout(with: context)
    UIView.animate(withDuration: 0.3) {
        self.collectionView.layoutIfNeeded()
    }