Согласно документации Apple (и рекламируемой на WWDC 2012), можно динамически установить макет на UICollectionView
и даже оживить изменения:
Обычно вы указываете объект макета при создании представления коллекции, но вы также можете динамически изменять макет представления коллекции. Объект макета сохраняется в свойстве collectionViewLayout. Установка этого свойства сразу обновляет макет сразу, без анимирования изменений. Если вы хотите анимировать изменения, вы должны вместо этого вызвать метод setCollectionViewLayout: анимированный.
Однако на практике я обнаружил, что 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
Контроллер устанавливает по умолчанию UICollectionViewFlowLayout
в viewDidLoad
и отображает одиночную ячейку на экране. Когда ячейки выбраны, контроллер создает еще один по умолчанию UICollectionViewFlowLayout
и устанавливает его в виде коллекции с флагом animated:YES
. Ожидаемое поведение заключается в том, что ячейка не перемещается. Фактическое поведение, однако, состоит в том, что ячейка прокручивается за кадром, и в этот момент даже невозможно прокрутить ячейку обратно на экране.
Глядя на консольный журнал, вы обнаружите, что contentOffset необъяснимо изменился (в моем проекте, от (0, 0) до (0, 205)). Я разместил решение для решения для неанимационного случая (i.e. animated:NO
), но поскольку мне нужна анимация, мне очень интересно узнать, есть ли у кого решение или обходной путь для анимированного случая.
Как замечание, я протестировал пользовательские макеты и получил то же поведение.