根据苹果的文档(并在 WWDC 2012 上进行宣传),可以动态设置 UICollectionView
的布局,甚至可以对更改进行动画处理:
通常在创建 collection view 时会指定布局对象,但也可以在运行时动态更改 collection view 的布局。布局对象存储在 collectionViewLayout 属性中。直接设置此属性将立即更新布局,而不会对更改进行动画处理。如果要对更改进行动画处理,则必须调用 setCollectionViewLayout:animated: 方法。
然而,在实践中,我发现 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
),但由于我需要动画,因此很想知道是否有任何解决方案或解决方法适用于带有动画的情况。
顺便说一句,我测试了自定义布局,并得到了相同的行为。
setCollectionViewLayout(_:animated:)
对我非常有用。只需像这样做collectionView.setCollectionViewLayout(expanded ? self.verticalFlowLayout : self.horizontalFlowLayout, animated: true)
- aheze