使用invalidateLayout加载数据后调整UICollectionViewCell的大小

时间:2014-05-18 22:45:29

标签: uicollectionview uicollectionviewcell uicollectionviewlayout

这个问题已被问过几次,但没有一个答案足够详细,我可以理解为什么/如何运作。作为参考,其他SO问题是:

How to update size of cells in UICollectionView after cell data is set?

Resize UICollectionView cells after their data has been set

Where to determine the height of a dynamically sized UICollectionViewCell?

我正在使用MVC,但为了保持简单,我可以说我有一个ViewController,它在ViewWillAppear中调用Web服务来加载一些数据。加载数据后,调用

[self.collectionView reloadData]

self.collectionView包含1个UICollectionViewCell(我们称之为DetailsCollectionViewCell)。

当创建self.collectionView时,它首先调用sizeForItemAtIndexPath然后调用cellForItemAtIndexPath。这对我来说是一个问题,因为只有在cellForItemAtIndexPath期间我通过以下方式将Web服务的结果设置为DetailsCollectionViewCell:

    cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"detailsCell" forIndexPath:indexPath];
    ((DetailsCollectionViewCell*)cell).details = result;

DetailsCollectionViewCell有一个属性详细信息的setter,它可以完成我需要先完成的一些工作,以了解正确的单元格大小应该是什么。

根据上面的链接问题,似乎是在调用cellForItemAtIndexPath之后触发sizeForItemAtIndexPath的唯一方法

[self.collectionView.collectionViewLayout invalidateLayout];

但是其他问题对我来说不起作用,因为虽然它调用sizeForItemAtIndexPath并允许我从DetailsCollectionViewCell中获取足够的信息来设置正确的高度,但在用户滚动UICollectionView和我之后才会更新UI猜测它与文档

中的这一行有关
  

在下一个视图布局更新周期中进行实际布局更新。

然而,我很难理解如何解决这个问题。我觉得我需要在DetailsCollectionViewCell上创建一个静态方法,我可以在第一个sizeForItemAtIndexPath传递期间传递Web服务结果,然后只缓存该结果。但我希望有一个简单的解决方案让UI自动更新。

谢谢,

P.S。 - 首先提出问题,希望我能正确遵守所有规则。

2 个答案:

答案 0 :(得分:2)

实际上,根据我的发现,调用invalidateLayout将导致在下一个单元格出列时为所有单元格调用sizeForItemAtIndexPath(这适用于iOS< 8.0,因为8.0它将在下一个视图布局更新中重新计算布局)。

所以我提出的解决方案是继承UICollectionView,并用这样的方法覆盖layoutSubviews:

- (void)layoutSubviews
{
    if ( self.shouldInvalidateCollectionViewLayout ) {
        [self.collectionViewLayout invalidateLayout];
        self.shouldInvalidateCollectionViewLayout = NO;
    } else {
        [super layoutSubviews];        
    }
}

然后在setNeedsLayout中调用cellForItemAtIndexPath并将shouldInvalidateCollectionViewLayout设置为YES。这适用于iOS> = 7.0。我也用这种方式实现了估计的项目大小。 THX。

答案 1 :(得分:0)

这是我的案例和解决方案。

我的collectionView在一个scrollView中,我希望我的collectionView和她的单元格在我滚动我的scrollView时调整大小。

所以在我的UIScrollView委托方法中:scrollViewDidScroll:

[super scrollViewDidScroll:scrollView];

if(scrollView.contentOffset.y>0){

    CGRect lc_frame = picturesCollectionView.frame;
    lc_frame.origin.y=scrollView.contentOffset.y/2;
    picturesCollectionView.frame = lc_frame;
}
else{

    CGRect lc_frame = picturesCollectionView.frame;
    lc_frame.origin.y=scrollView.contentOffset.y;
    lc_frame.size.height=(3*(contentScrollView.frame.size.width/4))-scrollView.contentOffset.y;
    picturesCollectionView.frame = lc_frame;

    picturesCollectionViewFlowLayout.itemSize = CGSizeMake(picturesCollectionView.frame.size.width, picturesCollectionView.frame.size.height);
    [picturesCollectionViewFlowLayout invalidateLayout];
}

我必须重新设置collectionViewFlowLayout单元格大小然后使其布局无效。 希望它有所帮助!