根据苹果公司的文档(并在2012年的 WWDC 大会上吹捧) ,可以动态设置 UICollectionView
的布局,甚至动画化更改:
通常在创建集合视图时指定布局对象,但也可以动态更改集合视图的布局。布局对象存储在 CollectionViewLayout 属性中。设置此属性直接立即更新布局,而不使更改具有动画效果。如果希望对更改进行动画处理,则必须调用 setCollectionViewLayout: animed: 方法。
然而,在实践中,我发现 UICollectionView
对 contentOffset
进行了令人费解甚至无效的更改,导致单元格移动不正确,使得该特性实际上无法使用。为了说明这个问题,我将下面的示例代码放在一起,这些代码可以附加到拖放到故事板中的默认集合视图控制器上:
#import <UIKit/UIKit.h>
@interface MyCollectionViewController : UICollectionViewController
@end
@implementation MyCollectionViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"CELL"];
self.collectionView.collectionViewLayout = [[UICollectionViewFlowLayout alloc] init];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"CELL" forIndexPath:indexPath];
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"contentOffset=(%f, %f)", self.collectionView.contentOffset.x, self.collectionView.contentOffset.y);
[self.collectionView setCollectionViewLayout:[[UICollectionViewFlowLayout alloc] init] animated:YES];
NSLog(@"contentOffset=(%f, %f)", self.collectionView.contentOffset.x, self.collectionView.contentOffset.y);
}
@end
控制器在 viewDidLoad
中设置默认的 UICollectionViewFlowLayout
,并在屏幕上显示单个单元格。当单元格被选中时,控制器创建另一个默认 UICollectionViewFlowLayout
并将其设置为集合视图中的 animated:YES
标志。预期的行为是单元格不移动。然而,实际的行为是单元格向屏幕外滚动,此时甚至不可能向屏幕上滚动单元格。
查看控制台日志可以发现 contentOffset 发生了令人费解的变化(在我的项目中,从(0,0)变为(0,205))。我发布了一个解决方案的 非动画案例的解决方案(i.e. animated:NO
) ,但因为我需要动画,我很有兴趣知道是否有人有一个解决方案或工作区的动画情况。
作为附带说明,我已经测试了自定义布局,并得到了相同的行为。