动画展示UICollectionView的框架和布局变化

21

我正在尝试创建这样一个效果: 在更改UICollectionView的框架大小的同时,改变其布局。

最初,collectionView布局呈现为全屏的“缩略图”画廊样式。

将框架调整为狭长条后,我想呈现“胶片带”样式的布局。

两种布局都能独立正常工作。

我尝试了类似于以下代码:

[UIView animateWithDuration:1
                          delay:0.0
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
                         self.collectionview.frame = newFrame; // animate the frame size


                     }
                     completion:^(BOOL finished) {
                        [self.collectionView.collectionViewLayout invalidateLayout];

    [self.collectionView setCollectionViewLayout:filmstriplayout animated:YES];    // now set the new layout
                     }];

但它看起来非常不流畅,而且未按预期调整大小。

是否有一种方法可以在动画更改的同时同时更改 collectionview 布局和框架大小?


你是否曾经得到一个好的解决方案?performBatchUpdates:withCompletion:是不错的,但无法帮助组合动画framecontentOffset的变化。我想要实现平滑地动画缩放反弹,其中我的布局和contentOffset取决于缩放。 - Benjohn
@Benjohn,你找到好的解决方案了吗?我也遇到了同样的问题,现有的答案并不理想... - aheze
1
@aheze 抱歉,我不知道——它比我现在能记得的还要久远 :-/ - Benjohn
3个回答

21

我没有一个具体的答案,但有几个建议可以考虑。

UICollectionView 不总是能够优雅地处理切换布局实例。这里有一个很好的讨论该问题以及一些解决方法

但在实践中,我实际上做的是在单个布局对象中实现两种布局,该对象知道如何在布局模式之间切换。我发现在批量更新块中切换布局模式比使用两个不同布局实例的setCollectionViewLayout要少出问题:

[self.collectionView performBatchUpdates:^{    MyLayout *layout = (MyLayout *)self.collectionView.collectionViewLayout;    layout.mode = otherLayoutMode;} completion:nil];

你使用 performBatchUpdates: 做什么? - alltom
在更新期间设置一个新实例,这是认真的吗?它最终会导致您的应用程序崩溃。 - Abdul Yasin

20

先设置网格单元的大小,例如 gridItemSize = CGSizeMake(98, 98);,然后执行 UICollectionView 的批量动作,集合视图中的项会带有动画效果改变它们的大小。 :)

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout*)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
   return CGSizeMake(gridItemSize.width, gridItemSize.height);
}

[self.collectionview performBatchUpdates:^{
    [self.collectionview.collectionViewLayout invalidateLayout];
    [self.collectionview setCollectionViewLayout:self.collectionview.collectionViewLayout animated:YES];
} completion:^(BOOL finished) {    
}];

2
这些都很方便,但同时发生的动画帧更改怎么办?同样地,我认为,需要一个contentOffset改变?我也需要两者同时发生。 - Benjohn
在我的使用情况中,当我的flowLayout被滚动和静态时需要不同的布局。我的做法是:(1)在布局中设置一个标志,并使用上面的代码使布局失效;(2)使用默认的collectionViewMethod滚动到IndexPath动画;(3)重置布局标志并再次使用上述代码将其动画回原始状态。我无法通过同时动画它们来实现所需的结果,因此我只是排队了这些动画。 - marcelosalloum
这里的 [self.collectionview.collectionViewLayout invalidateLayout]; 很奇怪,会导致动画中出现错误。 - surfrider

-3

每当您更新CollectionView时,请使用以下简单技巧:

[self.collectionView removeFromSuperview]; //First remove the Collection View

//Relocate the view with layouts
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.minimumInteritemSpacing = 10;
layout.minimumLineSpacing = 10;

 self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.width,100) collectionViewLayout:layout];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
[self.collectionView reloadData];

[self.view addSubview:self.collectionView];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接