UIView анимации плохо взаимодействуют - PullRequest
3 голосов
/ 09 мая 2009

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

В основном: У меня есть приложение для iPhone, которое включает кнопку «а» в корневом представлении. Нажатие «a» перемещает представление в стек контроллера навигации с перевернутой анимацией. Выдвинутый вид имеет кнопку, чтобы вернуть вид обратно в корень.

Базовый код:

- (IBAction)pushOneView{
TheAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight 
                    forView:delegate.navigationController.view cache:NO];
[delegate.navigationController 
            pushViewController:oneViewController animated:NO];
[UIView commitAnimations];

}

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

Корневое представление также включает в себя подпредставление ('panelView') и еще одну кнопку 'b'. PanelView может отображать любое из двух других подпредставлений - касание перестановок «b» между этими подпредставлениями с анимацией вращения. Код:

-(IBAction)swapPanels{
UIViewController *coming;
UIViewController *going;
float rotation;

if (self.aPanel.view.superview == nil) {
    coming = aPanel;
    going = bPanel;
    rotation = 3.14;
}
else {
    coming = bPanel;
    going = aPanel;
    rotation = -3.14;
}

// First half of spin
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
CGAffineTransform swirlTransform = CGAffineTransformMakeRotation(rotation);
panelView.transform = swirlTransform;
[panelView setAlpha:0.1];
[UIView commitAnimations];

// Finish spin
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
CGAffineTransform secondTransform = 
                        CGAffineTransformRotate(swirlTransform, rotation);
panelView.transform = secondTransform;
[panelView setAlpha:1];
[UIView commitAnimations];

// Swap the panels
[going.view removeFromSuperview];
[panelView insertSubview:coming.view atIndex:0];

}

Это также, кажется, работает нормально. Каждая из сменных панелей содержит сборщик и несколько ярлыков.

Однако я заметил, что переход 'a' становится медленным и прерывистым, если переход 'b' был выполнен до него. Другими словами, если я запускаю приложение, запускаю «а» взад-вперед несколько раз, оно работает гладко. Затем выполните упражнение «б» взад и вперед несколько раз. Затем попробуйте снова «a» ... «a» теперь прерывисто и будет оставаться таковым до перезапуска приложения.

Это на 100% повторяется. Использование симулятора незаметно, но на устройстве это очевидно. Я проверил на утечки - ни один не показан инструментом утечки. Если анимация удалена из операции 'b' (просто закомментируйте шаги анимации), эффект на 'a' будет , а не , наблюдаемый после осуществления подвидения подстановки 'b'. Если съемники снимаются с перьев сменной панели, эффект аналогичным образом устраняется. Если для анимационного перехода «a» задано значение «кэшировать», то после «b» он не заикается посередине, а, похоже, игнорирует анимацию, просто переключая представление (это может быть вопросом восприятия).

В случае, если мне неясно: я НЕ запускаю эти отдельные операции одновременно. Анимация «a» после того, как «b» была выполнена - и завершена, - не такая, как если бы «b» никогда не выполнялась. Нужно ли проводить очистку после анимации? Является ли мой код подкачки ошибочным? Или ...?

Заранее спасибо за любые предложения.

Ответы [ 2 ]

8 голосов
/ 09 мая 2009

У вас есть две перекрывающиеся анимации в разделе 'b'. Когда вы создаете анимацию, используя блок begin / commit, она передается фоновому потоку для выполнения. В вашем разделе 'b' две анимации, которые должны быть последовательными, фактически запускаются практически одновременно. Это может вызвать странное поведение, например, то, что вы видите.

Я бы рекомендовал добавить обратный вызов в вашей первой анимации к методу делегата, используя следующий код:

[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(rotationAnimationFinished:finished:context:)];

в вашем первом анимационном блоке в 'b' (часть "Первая половина вращения"). Затем вам нужно определить метод обратного вызова в вашем классе, в этом случае

- (void)rotationAnimationFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context;

Внутри этого метода делегата, который будет вызываться после завершения первой части анимации вращения, поместите оставшийся код из вашего метода 'b' (все после вашего комментария "Закончить вращение").

Разделяя эти анимации, это может предотвратить странность, которую вы видите.

2 голосов
/ 09 мая 2009

Ответ Брэда действительно , по-видимому, привел меня к решению: симптомы продолжали наводить на мысль, что что-то из-за запуска этих 'b' анимаций оставило систему в другом состоянии, чем когда она запускалась. Наконец, мне пришло в голову, что свойство transform PanelView осталось заданным после анимации 'b' ... и, возможно, это повлияло на дальнейшую анимацию суперпредставления, содержащего panelView.

Итак, я настроил метод, как предложил Брэд, чтобы он выполнялся после завершения анимации 'b' - но все, что делает этот метод, это устанавливает преобразование panelView обратно по умолчанию: CGAffineTransformIdentity:

  • (void) spinFinished: (NSString *) animationID закончено: (BOOL) завершено контекст: (void *) context { panelView.transform = CGAffineTransformIdentity; } * +1010 *

С этим на месте выполнение анимации 'a' после 'b' кажется нормальным. Итак, еще раз спасибо, Брэд, за вашу помощь здесь. Это много ценится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...