Восстановить пре-iOS7 UINavigationController pushViewController animation
Итак. Просто начал переводить мой IOS-код в IOS7 и столкнулся с некоторой проблемой.
У меня есть UINavigationController
, у которого есть дочерние ViewControllers, и я использую pushViewController
для отображения следующих представлений. Чтобы создать анимацию параллакса с набором изображений, при настройке UINavigationController
для анимации набора UIImageViews
, а у моих дочерних ViewControllers есть self.backgroundColor = [UIColor clearColor]
, прозрачность.
Так как iOS7, способ, в котором UINavController
оживляет его дочерние vc, обновляется, частично перемещая текущий контроллер представления, а сверху нажимает новый диспетчер представлений, моя анимация параллакса выглядит дерьмо. Я вижу, что предыдущий VC движется немного, а затем исчезает. Есть ли способ восстановить предыдущую анимацию pushTecViewController UINavigationController
? Я не могу найти это в коде.
WelcomeLoginViewController* welcomeLoginViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"WelcomeLogin"];
[self.navigationController pushViewController:welcomeLoginViewController animated:YES];
Даже попытался использовать:
[UIView animateWithDuration:0.75
animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[self.navigationController pushViewController:welcomeLoginViewController animated:NO];
[UIView setAnimationTransition:<specific_animation_form> forView:self.navigationController.view cache:NO];
}];
Есть ли у кого-нибудь подсказки?
Ответы
Ответ 1
Спасибо, ребята, за отзывы. Нашел решение, полностью воссоздающее поведение UINavigationController. Когда я почти закончил, я столкнулся с решением Ника Локвуда:
https://github.com/nicklockwood/OSNavigationController
OSNavigationController - это повторная реализация UINavigationController с открытым исходным кодом. В настоящее время он имеет только часть функциональности UINavigationController, но долгосрочная цель - реплицировать 100% функций.
OSNavigationController на самом деле не предназначен для использования как есть. Идея заключается в том, что вы можете разветкить ее, а затем легко настроить внешний вид и поведение в соответствии с любыми специальными требованиями, которые могут иметь ваше приложение. Настройка OSNavigationController намного проще, чем попытка настроить UINavigationController из-за того, что код открыт, и вам не нужно беспокоиться о частных методах, недокументированном поведении или изменениях реализации между версиями.
Переопределив мой UINavigationController своим кодом, я смог работать с фоновыми изображениями в UINavigationcontrollers
Спасибо!
Ответ 2
Мне удалось переделать новый тип перехода, создав категорию для UINavigationController
. В моем случае мне нужно было вернуть его в старый стиль перехода, потому что у меня есть прозрачные viewControllers, которые скользят по статическому фону.
-
UINavigationController + Retro.h
@interface UINavigationController (Retro)
- (void)pushViewControllerRetro:(UIViewController *)viewController;
- (void)popViewControllerRetro;
@end
-
UINavigationController + Retro.m
#import "UINavigationController+Retro.h"
@implementation UINavigationController (Retro)
- (void)pushViewControllerRetro:(UIViewController *)viewController {
CATransition *transition = [CATransition animation];
transition.duration = 0.25;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[self.view.layer addAnimation:transition forKey:nil];
[self pushViewController:viewController animated:NO];
}
- (void)popViewControllerRetro {
CATransition *transition = [CATransition animation];
transition.duration = 0.25;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[self.view.layer addAnimation:transition forKey:nil];
[self popViewControllerAnimated:NO];
}
@end
Ответ 3
У меня та же проблема с четкими цветами фона и дрянной анимацией, поэтому я создаю настраиваемый переход для ViewController с новым API iOS7. Все, что вам нужно, это просто установить делегат для вашего контроллера навигации:
// NavigationController does not retain delegate, so you should hold it.
self.navigationController.delegate = self.navigationTransitioningDelegate;
Просто добавьте эти файлы в свой проект: MGNavigationTransitioningDelegate.
Ответ 4
У меня возникла проблема, когда, когда UIViewController A сделал pushViewController, чтобы нажимать UIViewController B, анимация push остановится примерно на 25%, остановится, а затем переместит B в остальной части пути.
Этот DID НЕ происходит на iOS 6, но как только я начал использовать iOS 7 в качестве базового SDK в XCode 5, это начало происходить.
Исправление состоит в том, что в контроллере представления B не было набора backgroundColor в его корневом представлении (корневой вид - это тот, который является значением viewController.view, которое вы обычно устанавливаете в loadView). Исправлена проблема с установкой backgroundColor в этом корневом инициализаторе.
Мне удалось исправить это следующим образом:
// CASE 1: The root view for a UIViewController subclass that had a halting animation
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
// Do some initialization ...
// self.backgroundColor was NOT being set
// and animation in pushViewController was slow and stopped at 25% and paused
}
return self;
}
// CASE 2: HERE IS THE FIX
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
// Do some initialization ...
// Set self.backgroundColor for the fix!
// and animation in pushViewController is no longer slow and and no longer stopped at 25% and paused
self.backgroundColor = [UIColor whiteColor]; // or some other non-clear color
}
return self;
}
Ответ 5
Во-первых, я не использую раскадровки. Я пробовал использовать UINavigationController + Retro. По какой-то причине UINavigationController с трудом освобождает UIViewController в верхней части стека. Здесь решение, которое работает для меня с использованием пользовательского перехода iOS 7.
-
Установите делегат для себя.
navigationController.delegate = self;
-
Объявите этот UINavigationControllerDelegate.
- (id<UIViewControllerAnimatedTransitioning>)navigationController (UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
TransitionAnimator *animator = [TransitionAnimator new];
animator.presenting = YES;
return animator;
}
Обратите внимание, что он будет вызван только тогда, когда для анимированного настроено значение YES. Например
[navigationController pushViewController:currentViewController animated:YES];
-
Создайте класс аниматора, расширяющий NSObject. Я назвал мой TransitionAnimator, который был изменен из TeehanLax TLTransitionAnimator внутри UIViewController-Transitions-Example.
TransitionAnimator.h
#import <Foundation/Foundation.h>
@interface TransitionAnimator : NSObject <UIViewControllerAnimatedTransitioning>
@property (nonatomic, assign, getter = isPresenting) BOOL presenting;
@end
TransitionAnimator.m
#import "TransitionAnimator.h"
@implementation TransitionAnimator
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
return 0.5f;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
if (self.presenting) {
//ANIMATE VC ENTERING FROM THE RIGHT SIDE OF THE SCREEN
[transitionContext.containerView addSubview:fromVC.view];
[transitionContext.containerView addSubview:toVC.view];
toVC.view.frame = CGRectMake(0, 0, 2*APP_W0, APP_H0); //SET ORIGINAL POSITION toVC OFF TO THE RIGHT
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
fromVC.view.frame = CGRectMake(0, (-1)*APP_W0, APP_W0, APP_H0); //MOVE fromVC OFF TO THE LEFT
toVC.view.frame = CGRectMake(0, 0, APP_W0, APP_H0); //ANIMATE toVC IN TO OCCUPY THE SCREEN
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}else{
//ANIMATE VC EXITING TO THE RIGHT SIDE OF THE SCREEN
}
}
@end
Используйте флаг представления, чтобы указать направление, в котором вы хотите оживить или когда-либо условие, которое вы предпочитаете. Здесь ссылка на ссылку Apple.
Ответ 6
Просто добавьте:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Это:
[[self window] setBackgroundColor:[UIColor whiteColor]];
Конечный результат:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions {
[[self window] setBackgroundColor:[UIColor whiteColor]];
// Override point for customization after application launch.
return YES;
}
Ответ 7
Очевидно, что в iOS7 новый способ определяет ваши собственные пользовательские переходы UIViewController. Посмотрите в документах для UIViewControllerTransitioningDelegate. Кроме того, здесь ссылка на статью об этом: http://www.doubleencore.com/2013/09/ios-7-custom-transitions/
Ответ 8
Найден еще один отличный ресурс, который поможет:
http://www.teehanlax.com/blog/custom-uiviewcontroller-transitions
Использование iOS7 TLTransitionAnimator для создания пользовательских анимаций
Ответ 9
Я проголосовал за @Arne, потому что считаю это самым элегантным решением этой проблемы. Я просто хотел бы добавить код, чтобы ответить на проблему @Bill из его комментария по решению @Arne. Вот цитата комментария:
Спасибо, это работает для меня. Однако, когда пользователь удаляет Back, он возвращается к обанкротившейся анимации (поскольку кнопка "Назад" не вызывает popViewControllerRetro). - Билл 3 октября в 12:36
Чтобы вызвать popViewControllerRetro при нажатии кнопки "Назад" , вы можете выполнить небольшой взлом, чтобы достичь этого. Перейдите в свой толкаемый контроллер представления, импортируйте UIViewController + Retro.h и добавьте этот код в свой метод viewWillDisappear:
- (void)viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
[self.navigationController popViewControllerRetro];
}
[super viewWillDisappear:animated];
}
Этот оператор if обнаружит, когда нажата кнопка "Назад" , и вызовет popViewControllerRetro из класса категории.
С уважением.