UIScrollView с пользовательским layoutSubviews больше не анимируется - PullRequest
1 голос
/ 20 марта 2012

У меня есть подкласс UIScrollView, который я использую для слайд-шоу изображений с бесконечной прокруткой и круговым слайд-шоу.

Раньше я анимировал переход следующим образом: (потому что я хотел, чтобы переход был медленнее)

[UIView animateWithDuration:1.0 
                      delay:0 options:(UIViewAnimationCurveEaseOut)
                 animations:^{
                         self.scrollView.contentOffset = newOffset;}
                 completion:NULL];

И это сработало просто отлично.

Затем я посмотрел лекцию «Расширенные методы прокрутки» с WWDC 2011, и они рекомендуют осуществлять бесконечную прокрутку путем переопределения layoutSubviews.

Итак, я изменил свою реализацию и переопределил layoutSubviews

Как только я это сделал, анимация перехода перестала работать.

Если я закомментирую свой пользовательский макет Subviews - он снова заработает!

Почему ??

Что можно сделать, чтобы создать собственную анимацию прокрутки при переопределении layoutSubviews?

Спасибо!

1 Ответ

3 голосов
/ 20 марта 2012

ОК, думаю, я нашел проблему и возможное решение.

Ключ к пониманию проблемы - понимание того, что при вызове

[UIView animateWithDuration...]

все свойства, которые вы изменяетевнутри блока анимации немедленно изменяются .Они не меняются по мере выполнения анимации (визуально).

Так что в моем случае я анимирую contentOffset к своему целевому значению.Эта операция немедленно вызывает layoutSubviews.

В моей реализации layoutSubviews я проверяю, было ли накоплено достаточно движений.Если это так - я переставляю свои ImageViews и устанавливаю для contentOffset начальное значение .Как только я это сделаю, больше ничего не нужно анимировать, потому что ничего не изменилось!

  1. Animate contentOffset to X:
    • вызывает setContentOffset для X:
      • вызывает layoutSubview
        • Устанавливает contentOffset обратно в Y!(после перестановки видов)
    • Ничего не оживлять на этом этапе ...

Возможное исправление

Я не уверен, что это правильный способ, но он работает.Поэтому нам нужно убедиться, что в layoutSubviews не будет внесено никаких изменений, пока мы находимся в середине анимационного блока.

Поэтому я создал переменную экземпляра BOOL с именем isAnimating и соответствующим образом установил ее в анимации.блок:

self.isAnimating = YES;
[UIView animateWithDuration:self.transitionDuration 
                      delay:0 
                    options:(UIViewAnimationOptionCurveEaseOut) 
                 animations:^{
    self.contentOffset = newOffset;
}

                 completion:^(BOOL finished) {
        self.isAnimating = NO;
        [self setNeedsLayout];
}];

Теперь в макете Subviews нам нужно учесть isAnimating:

-(void) layoutSubviews
{
    [super layoutSubviews];
    if (self.isAnimating == NO)
    {
        [self rearrangeIfNecessary];
    }
}

И снова работает!

...