【问题标题】:Resize UICollectionView cells after their data has been set设置数据后调整 UICollectionView 单元格的大小
【发布时间】:2012-11-24 21:13:11
【问题描述】:

我的 UICollectionView 单元格包含带有多行文本的 UILabel。在标签上设置文本之前,我不知道单元格的高度。

-(CGSize)collectionView:(UICollectionView *)collectionView
                 layout:(UICollectionViewLayout*)collectionViewLayout
 sizeForItemAtIndexPath:(NSIndexPath *)indexPath;

这是我研究单元格大小的初始方法。但是,这是在从情节提要中创建单元之前调用的。

有没有办法在渲染后对集合进行布局和调整单元格的大小,并且我知道单元格的实际大小?

【问题讨论】:

标签: objective-c uicollectionview uicollectionviewcell


【解决方案1】:

嘿,在上面的delegate 方法本身中,您可以使用以下棘手的方法计算UILabel 的大小,并根据该计算返回UICollectionViewCell size

    // Calculate the expected size based on the font and 
    // linebreak mode of your label
    CGSize maximumLabelSize = CGSizeMake(9999,9999);

    CGSize expectedLabelSize = 
     [[self.dataSource objectAtIndex:indexPath.item] 
             sizeWithFont:[UIFont fontWithName:@"Arial" size:18.0f] 
        constrainedToSize:maximumLabelSize 
            lineBreakMode:NSLineBreakByWordWrapping];

【讨论】:

    【解决方案2】:

    我认为您正在寻找可以调用 UICollectionView 的 .collectionViewLayout 属性的 invalidateLayout 方法。此方法会重新生成您的布局,在您的情况下,这意味着还调用-collectionView: layout: sizeForItemAtIndexPath:,这是反映您所需项目大小的正确位置。 Jirune 指出了如何计算它们的正确方向。

    invalidateLayout 的用法示例可以在here 中找到。另请参阅有关该方法的 UICollectionViewLayout 文档:

    使当前布局无效并触发布局更新。

    讨论:

    您可以随时调用此方法来更新布局信息。此方法使集合视图本身的布局无效并立即返回。因此,您可以从同一个代码块中多次调用此方法,而不会触发多次布局更新。实际的布局更新发生在下一个视图布局更新周期。

    编辑:

    对于包含自动布局约束的storyboard collection view,需要覆盖UIViewControllerviewDidLayoutSubviews方法,并在该方法中调用invalidateLayout collection view layout。

    - (void)viewDidLayoutSubviews {
        [super viewDidLayoutSubviews];
        [yourCollectionView.collectionViewLayout invalidateLayout];
    }
    

    【讨论】:

    • 我正在按照你的实现方法,我遇到了一个问题:在调用invalidateLayout 后,有时单元格会消失/变得不可见,所以我无法在sizeForItemAtIndexPathcellForItemAtIndexPath 中获取它们。顺便说一句,我使用单元格来获取它们的大小,我没有单独的商店。
    • 太棒了!一直停留在单元格宽度上,因为它是通过自动布局分配的,所以没有改变,但是在阅读了这个解决方案之后,我确实明白了这一点。附言我放了自动布局问题的代码,希望你不要介意。
    • 非常感谢!我不知道这会解决问题!我正在调用 reloadData,这是一项代价高昂的操作,但它并没有给我预期的结果。
    • viewDidLayoutSubviews 中调用[collectionViewLayout invalidateLayout] 给了我一个无限循环。
    【解决方案3】:

    继承 UICollectionViewCell 并像这样覆盖layoutSubviews

    您将在此将单元格前缘和后缘锚定到 collectionView

    override func layoutSubviews() {
            super.layoutSubviews()
    
            self.frame = CGRectMake(0, self.frame.origin.y, self.superview!.frame.size.width, self.frame.size.height)
        }
    

    【讨论】:

      【解决方案4】:
      - (void)viewDidLoad {
          self.collectionView.prefetchingEnabled = NO;
      }
      

      在 iOS 10 中,prefetchingEnabled 默认为 YES。当YES 时,集合视图会在显示单元格之前提前请求它们。它会导致 iOS 10 崩溃

      【讨论】:

      • 虽然欢迎使用此代码 sn-p,并且可能会提供一些帮助,但它会是 greatly improved if it included an explanation of howwhy 这解决了问题。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人!请edit您的答案添加解释,并说明适用的限制和假设。
      • @TobySpeight 在 iOS10 中,prefetchingEnabled 默认为 YES。如果为“是”,则集合视图会在显示单元格之前提前请求它们。它导致iOS10崩溃
      • 这似乎是一个很好的解释 - 请edit您的回答来合并它。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      • 2021-09-28
      • 2016-03-12
      • 1970-01-01
      • 2013-02-24
      • 1970-01-01
      相关资源
      最近更新 更多