UIPercentDrivenInteractiveTransition, выдающий постороннюю анимацию по завершении

StackOverflow https://stackoverflow.com//questions/23047350

  •  21-12-2019
  •  | 
  •  

Вопрос

Я использую интерактивный пользовательский push-переход с UIPercentDrivenInteractiveTransition.Устройство распознавания жестов успешно вызывает контроллер взаимодействия updateInteractiveTransition.Аналогично, анимация успешно завершается, когда я вызываю контроллер взаимодействия finishInteractiveTransition.

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

Кто-нибудь еще видел эту проблему и нашел решение, отличное от оптимизации анимации (что я, по общему признанию, должен делать в любом случае) и / или написания моих собственных контроллеров взаимодействия?Тот Самый UIPercentDrivenInteractiveTransition в этом подходе есть определенная элегантность, но меня беспокоит тот факт, что он ведет себя недетерминированно.Видели ли другие такое поведение?Кто-нибудь знает о других решениях?

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

animation not right

Эта анимация генерируется:

  • неоднократно звонивший updateInteractiveTransition, прогрессирующее обновление с 0% до 40%;

  • мгновенная пауза (чтобы вы могли отличить интерактивный переход от анимации завершения, возникающей в результате finishInteractiveTransition);

  • затем звонит finishInteractiveTransition для завершения анимации;и

  • анимация контроллера анимации completion блокировать вызовы completeTransition для transitionContext, для того, чтобы все навести порядок.

Проведя некоторую диагностику, выясняется, что именно этот последний шаг запускает этот посторонний фрагмент анимации.Блок завершения контроллера анимации вызывается, когда анимация завершена, но как только я вызываю completeTransition, иногда он повторяет последний фрагмент анимации (особенно при использовании сложных анимаций).


Я не думаю, что это актуально, но это мой код для настройки навигационного контроллера для выполнения интерактивных переходов:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.navigationController.delegate = self;

    self.interationController = [[UIPercentDrivenInteractiveTransition alloc] init];
}

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                  animationControllerForOperation:(UINavigationControllerOperation)operation
                                               fromViewController:(UIViewController*)fromVC
                                                 toViewController:(UIViewController*)toVC
{
    if (operation == UINavigationControllerOperationPush)
        return [[PushAnimator alloc] init];

    return nil;
}

- (id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController*)navigationController
                          interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController
{
    return self.interationController;
}

Мой PushAnimator является:

@implementation PushAnimator

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
    return 5.0;
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIViewController* toViewController   = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    [[transitionContext containerView] addSubview:toViewController.view];
    toViewController.view.frame = CGRectOffset(fromViewController.view.frame, fromViewController.view.frame.size.width, 0);;

    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        toViewController.view.frame = fromViewController.view.frame;
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

@end

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

К вашему сведению, я провел этот эксперимент с распознавателем жестов:

- (void)handlePan:(UIScreenEdgePanGestureRecognizer *)gesture
{
    CGFloat width = gesture.view.frame.size.width;

    if (gesture.state == UIGestureRecognizerStateBegan) {
        [self performSegueWithIdentifier:@"pushToSecond" sender:self];
    } else if (gesture.state == UIGestureRecognizerStateChanged) {
        CGPoint translation = [gesture translationInView:gesture.view];
        [self.interactionController updateInteractiveTransition:ABS(translation.x / width)];
    } else if (gesture.state == UIGestureRecognizerStateEnded ||
               gesture.state == UIGestureRecognizerStateCancelled)
    {
        CGPoint translation = [gesture translationInView:gesture.view];
        CGPoint velocity    = [gesture velocityInView:gesture.view];
        CGFloat percent     = ABS(translation.x + velocity.x * 0.25 / width);

        if (percent < 0.5 || gesture.state == UIGestureRecognizerStateCancelled) {
            [self.interactionController cancelInteractiveTransition];
        } else {
            [self.interactionController finishInteractiveTransition];
        }
    }
}

Я также сделал это, позвонив в updateInteractiveTransition и finishInteractiveTransition вручную (исключив распознаватель жестов из уравнения), и он по-прежнему демонстрирует это странное поведение:

[self performSegueWithIdentifier:@"pushToSecond" sender:self];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [self.interactionController updateInteractiveTransition:0.40];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.interactionController finishInteractiveTransition];
    });
});

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

Но мне было интересно, придумал ли кто-нибудь какие-нибудь другие приемы для использования UIPercentDrivenInteractiveTransition со сложной анимацией.

Это было полезно?

Решение

Я видел нечто подобное.У меня есть два возможных обходных пути.Один из них заключается в использовании отложенной производительности в обработчике завершения анимации:

} completion:^(BOOL finished) {
        double delayInSeconds = 0.1;
        dispatch_time_t popTime = 
             dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            BOOL cancelled = [transitionContext transitionWasCancelled];
            [transitionContext completeTransition:!cancelled];
        });
       self.interacting = NO;
}];

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

Другие советы

Эта проблема возникает только в симуляторе.

РЕШЕНИЕ:self.interactiveAnimator.Скорость завершения = 0,999;

сообщение об ошибке приведено здесь: http://openradar.appspot.com/14675246

Причиной этой ошибки в моем случае была установка рамки анимируемого вида несколько раз.Я устанавливаю рамку просмотра только ОДИН раз, и это устранило мои проблемы.

Таким образом, в этом случае кадр "toViewController.view" был установлен ДВАЖДЫ, что привело к нежелательному поведению анимации

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top