Я использую интерактивный пользовательский переход с помощью UIPercentDrivenInteractiveTransition
. Устройство распознавания жестов успешно вызывает контроллер взаимодействия updateInteractiveTransition
. Аналогично, анимация успешно завершается, когда я вызываю контроллер взаимодействия finishInteractiveTransition
.
Но иногда я получаю дополнительный бит отвлекающей анимации в конце (где, похоже, повторяется вторая часть анимации). При достаточно простых анимациях я редко вижу этот симптом на iPhone 5 (хотя я регулярно вижу его на симуляторе при работе на медленном ноутбуке). Если сделать анимацию более дорогостоящей (т.е. Много теней, нескольких видов, анимационных разных направлениях и т.д.), Частота этой проблемы на устройстве увеличивается.
Кто-нибудь еще видел эту проблему и выяснил решение, отличное от оптимизации анимаций (что я, по общему признанию, должен делать в любом случае) и/или написания своих собственных контроллеров взаимодействия? Подход UIPercentDrivenInteractiveTransition
имеет определенную элегантность, но мне неловко с тем, что он неверно ведет себя недетерминированно. Кто-нибудь видел это поведение? Кто-нибудь знает о других решениях?
Чтобы проиллюстрировать эффект, см. изображение ниже. Обратите внимание, что вторая сцена, красная точка, когда заканчивается анимация, повторяет вторую часть своей анимации второй раз.
Эта анимация генерируется:
-
повторно вызывающий
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
Обратите внимание, что когда я помещаю оператор регистрации, где я вызываю completeTransition
, я вижу, что этот посторонний бит анимации происходит после того, как я вызываю completeTransition
(даже если анимация действительно была выполнена в этой точке). Это предполагает, что эта дополнительная анимация могла быть результатом вызова completeTransition
.
FYI, я сделал этот эксперимент с распознающим жестом:
- (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
со сложными анимациями.