【问题标题】:UICollectionView with self-sizing cells resizes cells during insert/remove animationUICollectionView 与自调整单元格在插入/删除动画期间调整单元格大小
【发布时间】:2015-09-16 00:32:26
【问题描述】:

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

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

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

layout.estimatedItemSize = CGSizeMake(88.0, 88.0);

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

如何避免这种调整大小?我只针对 iOS 8.0 及更高版本,所以应该支持它。

【问题讨论】:

  • 您解决了这个问题吗?我也遇到了同样的问题!
  • 不,抱歉。我会在苹果论坛上再次询问。在 iOS 9 上它会直接崩溃,所以我一定是遗漏了一些东西。
  • 我在提出自己的类似问题后注意到了这一点:stackoverflow.com/questions/34045566/…。你找到解决办法了吗?
  • @AshleyMills 不,永远不会
  • 为集合视图自行调整大小是一场噩梦。

标签: ios ios8 autolayout uicollectionview


【解决方案1】:

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

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

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

查看示例项目here

【讨论】:

  • Self-Sizing cell 刚刚损坏,在 WWDC 演示案例之外无法使用
【解决方案2】:

为了避免单元格调整大小,请使用 InvalidationContext

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

【讨论】:

    【解决方案3】:
    1. estimatedItemSize 属性设置为适当的大小。

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

      -(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.In sizeForItemAtIndexPath 返回缓存大小(如果可用),否则估计大小。

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

    【讨论】:

    • 拯救了我的一天!但是我已经定制了流布局来缓存shouldInvalidateLayout(forPreferredLayoutAttributes的属性
    【解决方案4】:

    一个简单的解决方案是实现 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()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-26
      • 2012-05-20
      • 2021-09-28
      • 2020-06-26
      • 2020-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多