调整UICollectionViewCells的大小以始终填充UICollectionView

时间:2014-10-01 13:10:17

标签: ios animation uicollectionview uicollectionviewcell

我有一个水平滚动的UICollectionView,UICollectionViewCells和集合视图本身一样高,第三个宽(所以一次三个)。集合视图已分页并使用默认的Flow Layout。

单元格来自.xib文件,并使用“自动布局”将内容保留在原位。

我想要做的是让集合视图的高度在两个预定义高度之间切换,并且单元格的高度始终填充可用空间,即使在动画期间也是如此。

集合视图动画是通过将顶部约束设置为其超级视图来完成的,并且似乎有效:

UIView.animateWithDuration(0.5, animations: { () -> Void in
    self.collectionViewTopConstraint.constant = (self.collectionViewTopConstraint.constant == 50 ? 100 : 50)
    self.view.layoutIfNeeded()
})
然而,这使细胞保持不变。

我尝试在动画块的末尾添加以下内容:

self.collectionView.performBatchUpdates({ () -> Void in

}, completion: nil)

这几乎可以工作,但是细胞从一个高度交叉淡化到另一个高度,而不是仅仅改变高度,这看起来很糟糕。

我也尝试了以下内容:

self.collectionView.collectionViewLayout.invalidateLayout()

这可以达到同样的效果,但不是那么顺利。

此外,在这两种情况下,如果重复调用切换动画,我会收到此警告:

the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less than the height of the UICollectionView minus the section insets top and bottom values.

我做了很多研究,但我发现的一切都涉及自定义布局或在不同布局之间切换,我认为这些不适用于我,因为即使集合视图的高度发生变化,布局也使用相同的逻辑来定位元件。

有什么想法吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

我认为这可以通过在动画之前更改单元格的itemSize来实现。单元格的原始大小设置为如下所示的相同值,但没有+号* 50术语。

- (IBAction)toggleCollectionViewSize:(id)sender {
    self.collectionViewTopConstraint.constant = (self.collectionViewTopConstraint.constant == 50)? 100 : 50;
    NSInteger sign = (self.collectionViewTopConstraint.constant == 50)? 1 : -1;
    self.layout.itemSize = CGSizeMake(self.collectionView.frame.size.width/3.0 , self.collectionView.frame.size.height + sign*50);
    [UIView animateWithDuration:.5 animations:^{
        [self.view layoutIfNeeded];
    }];
}

我在顶部,中部和底部有视图的单元格上测试了这个。它看起来很不错,但底部视图有轻微的移动,我无法解释。当转换发生时,您仍然会对单元格略微褪色(其alpha值降低)。如果集合视图背景颜色与单元格背景颜色相同,则可以最小化此视觉效果。

编辑后:

如果使用计时器而不是animateWithDuration,效果会更好;我不会那样褪色。

-(void)viewWillLayoutSubviews {
    self.layout.itemSize = CGSizeMake(self.collectionView.bounds.size.width/3.0 , self.collectionView.bounds.size.height - 1); // the -1 suppresses a warning about the height that you get on every toggle. I still get one warning at the start.
}


- (IBAction)toggleCollectionViewSize:(id)sender {
    NSInteger sign = (self.topCon.constant == 50)? 1 : -1;
    [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:@selector(shrink:) userInfo:@(sign) repeats:YES];
}


-(void)shrink:(NSTimer *) aTimer {
    NSInteger sign = [aTimer.userInfo integerValue];
    self.topCon.constant += sign;
    if (self.topCon.constant == 100 || self.topCon.constant == 50) {
        [aTimer invalidate];
    }
}
相关问题