Расширенная анимация UICollectionView с использованием invalidateLayout-вызовов

Руководство по программированию UICollectionView говорит:

В дополнение к анимации операций вставки, удаления и перемещения, вы можете аннулировать макет в любое время и заставить его перерисовать его содержание. Недействительность макета не анимирует элементы напрямую; когда вы аннулируете макет, в представлении коллекции отображаются элементы в их новых расчетных позициях без оживления. Однако акт недействительности макета заставляет объект макета перемещать элементы в явном виде. В пользовательском макете вы можете использовать это поведение для размещать ячейки через регулярные промежутки времени и создавать анимированный эффект.

Я пытаюсь что-то вроде этого, где AnimationStep - это перечисление, используемое моим подклассом UICollectionViewFlowLayout, чтобы условно установить позиции плиток с трехступенчатой ​​анимацией:

-(void)update{
    [self animateLayoutAfterDelay:2.0 toStep:AnimationStepOne];
    [self animateLayoutAfterDelay:4.0 toStep:AnimationStepTwo];
    [self animateLayoutAfterDelay:6.0 toStep:AnimationStepThree];
}

-(void)animateLayoutAfterDelay:(NSTimeInterval)delay toStep:(MagazineLayoutAnimationStep)step {
    double delayInSeconds = delay;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [UIView animateWithDuration:2.0 animations:^{
            self.layout.animationStep = step;
            [self.layout invalidateLayout];
        }];
    });
}

Это имеет весьма непредсказуемые последствия. Некоторые клетки ожидают так, как я ожидал, некоторые скрываются и показываются или просто появляются в новых местах. Я помещал случайные цвета фона в ячейки, чтобы убедиться, что это может быть эффект UICollectionView, перерабатывающих ячейки, и, конечно же, это было так. Это объясняет некоторые странности, но не все.

Кто-нибудь знает, как Apple хочет, чтобы я анимировал ячейки и перемещал их?

(Мне нужно это, потому что мои элементы просмотра коллекции меняют размер, и я хочу изящную анимацию без какого-либо диагонального движения).

Ответ 1

Ответ на этот вопрос - использование промежуточных макетов.

[self.collectionView setCollectionViewLayout: layoutForStepOne animated:YES completion:^(BOOL finished) {
    [self.collectionView setCollectionViewLayout: layoutForStepTwo animated:YES completion:^(BOOL finished) {
        [self.collectionView setCollectionViewLayout: layoutForStepThree animated:YES];

    }];
}];

Ответ 2

Это просто:

Создайте новый экземпляр некоторого UICollectionViewLayout и используйте

- (void)setCollectionViewLayout:(UICollectionViewLayout *)layout animated:(BOOL)animated

чтобы установить макет вашего UICollectionView на этот новый объект макета. Убедитесь, что вы используете YES для анимированного параметра.

Изменить: Для выполнения многоэтапной анимации я бы попробовал

performBatchUpdates:completion:

и поместите следующее обновление в блок завершения и повторите.