Анимация кадра и изменение макета UICollectionView

Я пытаюсь создать эффект, при котором я меняю макет своего 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
                     }];

Но он выглядит очень изменчивым и не изменяет размер, как ожидалось.

Есть ли способ, с помощью которого я мог бы одновременно изменить макет представления коллекции и размер кадра при анимации изменения?


person Avner Barr    schedule 08.09.2013    source источник
comment
Вы когда-нибудь получали хорошее решение? performBatchUpdates:withCompletion: хорош, но не помогает совмещать анимированные изменения frame или contentOffset. Я хочу получить это для плавной анимации масштабирования, где мой макет и contentOffset зависят от масштабирования.   -  person Benjohn    schedule 02.08.2015
comment
@Benjohn ты нашел хорошее решение? Просто наткнулся на то же самое, и существующие ответы не идеальны...   -  person aheze    schedule 21.06.2021
comment
@aheze Извините, я не знаю — это было раньше, чем я могу вспомнить :-/   -  person Benjohn    schedule 21.06.2021


Ответы (3)


Сначала установите размер элемента сетки, например 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) {    
}];
person Zulqarnain    schedule 04.11.2013
comment
Это удобная штука, но а как насчет смены анимированных кадров, происходящей в то же время? Эквивалентно, я думаю, contentOffset изменение? Мне также нужно, чтобы оба произошли одновременно. - person Benjohn; 02.08.2015
comment
В моем случае мой flowLayout должен отличаться, когда он прокручивается и когда он статичен. Что я делаю: (1-й) устанавливаю флаг в макете и использую приведенный выше код, чтобы сделать макет недействительным; (2-й) анимация scrollToIndexPath с использованием метода collectionViewMethod по умолчанию; (3-й) сбросьте флаг макета и снова используйте приведенный выше код, чтобы вернуть его в исходное состояние. Я не мог добиться желаемых результатов, анимируя их одновременно, поэтому я просто поставил анимацию в очередь. - person marcelosalloum; 23.10.2019
comment
[self.collectionview.collectionViewLayout invalidateLayout]; тут странно, это приводит к багам в анимации. - person surfrider; 22.05.2020

У меня нет конкретного ответа, но есть несколько предложений для рассмотрения.

UICollectionView не всегда изящно обрабатывает переключение экземпляров макета. Вот хорошее обсуждение проблемы и некоторых обходных путей.

Но на практике я реализовал оба макета в одном объекте макета, который знает, как переключаться между режимами макета. Я обнаружил, что переключение режимов макета в блоке пакетного обновления менее проблематично, чем использование setCollectionViewLayout с двумя разными экземплярами макета:

[self.collectionView performBatchUpdates:^{
    MyLayout *layout = (MyLayout *)self.collectionView.collectionViewLayout;
    layout.mode = otherLayoutMode;
} completion:nil];
person Timothy Moose    schedule 08.09.2013
comment
Что вы используете performBatchUpdates:? - person alltom; 09.05.2014
comment
Установка нового экземпляра во время обновления, серьезно? В конечном итоге это приведет к сбою вашего приложения. - person Abdul Yasin; 02.02.2021

Вот простой трюк, когда вы обновляете 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];
person Shivam Singh    schedule 22.02.2016