IOS7 UIModalTransitionStyleFlipГоризонтальные отскоки после перехода

Я обновляю свое приложение для iOS 7, и я обнаружил странную проблему. Я представляю UIViewController, завернутый в UINavigationController с UIModalTransitionStyleFlipHorizontal.

В iOS 6 он работает нормально, но в iOS 7 панель навигации отскакивает после перехода. Это имеет какое-то отношение к строке состояния? Я установил прозрачность основной панели навигации на NO.

В окне Info.plist на панели состояния View на панели управления установлено значение NO.

И вот GIF, показывающий проблему в минимальном демонстрационном приложении:

enter image description here

Вот мой код:

feedNavigationController = [[UINavigationController alloc] init];
feedNavigationController.navigationBar.translucent = NO;

SettingsViewController *settingsVC = [[SettingsViewController alloc] init];

feedNavigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[feedNavigationController setViewControllers:[NSArray arrayWithObjects:settingsVC, nil]];

[self presentViewController:feedNavigationController animated:YES completion:nil];

Ответ 1

Кажется, это ошибка UIKit. Кажется, что решение этой проблемы разрешает следующее обходное решение.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self.navigationController.navigationBar.layer removeAllAnimations];
}

(Поместите это в контроллер просмотра, в котором вы переходите в).

Ответ 2

Чтобы решить эту проблему для присутствия и увольнения, я использую пользовательский переход iOS7.

Добавьте это в свой UIViewController:

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
    return (id<UIViewControllerAnimatedTransitioning>)self;
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
    return (id<UIViewControllerAnimatedTransitioning>)self;
}

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

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    UIView *containerView = [transitionContext containerView];


    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    [containerView addSubview:fromVC.view];

    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    [containerView addSubview:toVC.view];

    UIViewAnimationOptions animationOption = ([toVC.presentedViewController isEqual:fromVC])?UIViewAnimationOptionTransitionFlipFromLeft:UIViewAnimationOptionTransitionFlipFromRight;


    [UIView transitionFromView:fromVC.view
                        toView:toVC.view
                      duration:[self transitionDuration:transitionContext]
                       options:animationOption
                    completion:^(BOOL finished) {
                        [transitionContext completeTransition:YES];
                    }];
}

Чтобы использовать его, вам просто нужно было проверить, находитесь ли вы на iOS7 и установите переходDelegate:

YourVCWithTheCustomTransition* yourVC = [[YourVCWithTheCustomTransition alloc] init];

CGFloat deviceVersion = [UIDevice currentDevice].systemVersion.floatValue;
if(deviceVersion >= 7.0) [yourVC setTransitioningDelegate:yourVC];

[self presentModalViewController:yourVC animated:YES];
[yourVC release];

В моем случае у меня был пользовательский UINavigationController, в котором определен пользовательский переход: я не должен делать это каждый раз.

Ответ 3

Кажется, это ошибка UIKit. Кажется, что решение этой проблемы разрешает следующее обходное решение.

presentViewController (поместите это в контроллер просмотра, к которому вы переходите):

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self.navigationController.navigationBar.layer removeAllAnimations];
}

rejectViewControllerAnimated (поместите это в контроллер просмотра, который вы уволите):

- (void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];

    [self.navigationController.navigationBar.layer removeAllAnimations];
}

если вы не используете автоматический макет. вам нужно добавить это к контроллеру вида, который вы упускаете:

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];

    [self.view setNeedsLayout];
} 

Ответ 4

У меня была такая же проблема и я мог "решить ее" (это не реальное решение проблемы, но она выглядит отлично:)). Трюк представляет собой контроллер представления с помощью pushViewController/popViewController с анимацией UIView, чтобы сделать флип. Вот пример кода для представления контроллера вида:

UIViewController *viewController = [[UIViewController alloc] init];
[UIView transitionWithView:self.navigationController.view 
                  duration:0.5 
                   options:UIViewAnimationOptionTransitionFlipFromLeft 
                animations:^{
                   [self.navigationController pushViewController:viewController animated:NO];
                }
                completion:nil];

Отклонить его:

[UIView transitionWithView:self.navigationController.view 
                  duration:0.5 
                   options:UIViewAnimationOptionTransitionFlipFromRight 
                animations:^{
                   [self.navigationController popViewControllerAnimated:NO];
                }
                completion:nil];

Если вы не хотите, чтобы navigationBar на толкаемом контроллере просто вызывал [self.navigationController setNavigationBarHidden: YES animated: NO] в viewWillAppear. Я надеюсь, что этот подход поможет вам

Ответ 5

Для представления и представленного контроллера представления у меня есть UITableViewController внутри UINavigationController, оба настроены с использованием автоматической компоновки. Я заметил, что другие ответы не решают проблему, что при отключении tableView контроллера представления представления прыгает на 20 pt по вертикали.

Это решение решает эту проблему.

В представленном контроллере представления (как предложено Бен Паккардом):

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.navigationController.navigationBar.layer removeAllAnimations];
}

В контроллере представления представлений (как это было предложено частично пыльным):

- (void)viewWillLayoutSubviews{
    if (self.navigationController.presentedViewController) {
        [self.navigationController.navigationBar.layer removeAllAnimations];
        [self.tableView.layer removeAllAnimations];
    }
    [super viewWillLayoutSubviews];
}

Ответ 6

То же самое для меня. Что на самом деле работало, так это изменить стиль на CoverVertical, выглядит намного более плавным.