Панель навигации настраивается после вызова completeTransition: в пользовательском переходе
Моя цель - обеспечить масштабирование модального перехода от пользователя к виду, аналогичному тому, как иконки трамплинов увеличиваются при запуске приложений.
Представленный контроллер просмотра масштабируется правильно, но на панели навигации неправильная позиция находится в строке состояния. Эта позиция исправляется после вызова [transitionContext completeTransition: закончена];. Как я могу сделать это правильно с самого начала перехода?
Это экранная запись ошибки: http://youtu.be/7LKU4lzb-uw (сбой в шестой секунде записи)
Код UIViewControllerAnimatedTransitioning:
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *container = [transitionContext containerView];
CGPoint viewCenter = self.view.center;
CGSize viewSize = self.view.frame.size;
CGSize controllerSize = toViewController.view.frame.size;
CGFloat controllerFromX = viewCenter.x - (controllerSize.width / 2);
CGFloat controllerFromY = viewCenter.y - (controllerSize.height / 2);
CGAffineTransform transform = CGAffineTransformMakeTranslation(controllerFromX, controllerFromY);
transform = CGAffineTransformScale(transform, viewSize.width / controllerSize.width, viewSize.height / controllerSize.height);
if (self.reverse) {
[container insertSubview:toViewController.view belowSubview:fromViewController.view];
} else {
toViewController.view.transform = transform;
[container addSubview:toViewController.view];
}
[UIView animateKeyframesWithDuration:ZoomTransitioningDuration
delay:0
options:0
animations:^{
if (self.reverse) {
fromViewController.view.alpha = 0.0f;
fromViewController.view.transform = transform;
} else {
toViewController.view.transform = CGAffineTransformIdentity;
}
}
completion:^(BOOL finished) {
[transitionContext completeTransition:finished];
}];
}
Ответы
Ответ 1
Проблема заключается в том, что вы устанавливаете преобразование до вставки целевого представления контроллера представления в контейнер.
Переключение порядка должно исправить это:
if (self.reverse) {
[container insertSubview:toViewController.view belowSubview:fromViewController.view];
} else {
[container addSubview:toViewController.view];
toViewController.view.transform = transform;
}
Смотрите пункт 4 здесь. Поскольку вы применили преобразование до вставки представления контроллера навигации в качестве подпредставления, механизм компоновки не считает, что панель навигации находится в верхнем крае окна, и, следовательно, его не нужно настраивать, чтобы избежать строки состояния.
Ответ 2
Я нашел решение, хотя довольно хаки. Мне нужно вручную настроить рамку навигационной панели до начала анимации:
if (self.reverse) {
[container insertSubview:toViewController.view belowSubview:fromViewController.view];
} else {
toViewController.view.transform = transform;
[container addSubview:toViewController.view];
// fix navigation bar position to prevent jump when completeTransition: is called
if ([toViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*) toViewController;
UINavigationBar* bar = navigationController.navigationBar;
CGRect frame = bar.frame;
bar.frame = CGRectMake(frame.origin.x, frame.origin.y + 20.0f, frame.size.width, frame.size.height);
}
}
Ответ 3
Сначала добавьте toViewControllerView в ContainerView, затем установите преобразование toViewControllerView, как показано ниже.
[контейнер addSubview: toViewController.view];
toViewController.view.transform = transform;
Это решит проблему.
Ответ 4
Это все еще хак, основанный на Ondřej Mirtes ', но он работает лучше, если у вас есть строка состояния в вызове, и вы на iOS8
if([toViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navCtrl = (UINavigationController *)toViewController;
UINavigationBar *navBar = navCtrl.navigationBar;
if(navBar.frame.origin.y == 0 && navBar.frame.size.height == 44) {
navBar.frame = CGRectMake(0, 0, navBar.frame.size.width, fmin(44 + [UIApplication sharedApplication].statusBarFrame.size.height, 64));
}
}
Остается уродливым, хотя:/