iOS7 UIModalTransitionStyleFlipHorizontal springt nach dem Übergang

73

Ich aktualisiere meine App für iOS 7 und habe ein seltsames Problem entdeckt. Ich präsentiere einen UIViewController, der in einen UINavigationController mit eingeschlossen ist UIModalTransitionStyleFlipHorizontal.

In iOS 6 funktioniert es einwandfrei, aber in iOS 7 springt die Navigationsleiste nach dem Übergang. Hat das etwas mit der Statusleiste zu tun? Ich habe die Transluzenz der Hauptnavigationsleiste auf eingestellt NO.

In der Info.plist ist das Erscheinungsbild der View Controller-basierten Statusleiste auf NO gesetzt.

Und hier ist ein GIF, das das Problem in einer minimalen Demo-App zeigt:

Geben Sie hier die Bildbeschreibung ein

Hier ist mein Code:

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];
Rene
quelle
Leider kann das Video nicht gefunden werden.
Tim Bodeit
2
Ich habe das gleiche Problem.
Flypig
Genau das gleiche Problem, der GM-Build hat einige Biig-Probleme, collectionView reloadData ist auch eines!
JasonIM
1
Nicht für mich! iOS 8 hat immer noch dieses Problem. self.navigationController? .navigationBar.layer.removeAllAnimations () in view wird anscheinend für mich behoben.
nmdias
1
In meinem Projekt verwende ich unter iOS9 UIView TransitionFromView: toView: Dauer: Optionen: Abschluss: Um zwischen zwei Viewcontrollern zu wechseln und diesen Fehler zu beheben. Die folgenden Antworten lösten das Problem mit der Höhe der Navigationsleiste, aber nicht mit der Farbe des Tons.
eagle.dan.1349

Antworten:

54

Dies scheint ein UIKit-Fehler zu sein. Die folgende Problemumgehung scheint das Problem für mich zu lösen.

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

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

(Legen Sie diese im View - Controller Sie den Übergang zu ).

Ben Packard
quelle
Das hat bei mir funktioniert. Stellen Sie sicher, dass Sie dies im Root-View-Controller Ihres Navigations-Controllers tun, nicht im Navigations-Controller selbst.
Alexcash
Interessant - was genau passiert bei Entlassung?
Ben Packard
Das gleiche passiert bei Entlassung. Dies löst das Problem also nur teilweise. Wenn Sie dies dem Ansichts-Controller hinzufügen, mit dem der Übergang begonnen hat (dem Ansichts-Controller), wird das Problem beim Schließen und Zurückschalten nicht behoben.
Philip
Ich verstehe - ich schalte von einem Controller ohne Navigationsleiste aus, bin also nie darauf gestoßen. Technisch löst es die gestellte Frage;)
Ben Packard
5
Dies funktionierte bei mir beim ersten Aufruf der Animation, jedoch nicht bei nachfolgenden Aufrufen. Warum sollte das so sein, da es jedes Mal aufgerufen wird, wenn die Ansicht angezeigt wird? Wahnsinn.
Matt Miller
16

Um dieses Problem zu lösen und zu entlassen, verwende ich den benutzerdefinierten Übergang für iOS7.

Fügen Sie dies Ihrem UIViewController hinzu:

- (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];
                    }];
}

Um es zu verwenden, mussten Sie nur überprüfen, ob Sie unter iOS7 arbeiten, und das TransitionDelegate festlegen:

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];

In meinem Fall hatte ich einen benutzerdefinierten UINavigationController, in dem der benutzerdefinierte Übergang definiert ist: Ich muss dies nicht jedes Mal tun.

EricD
quelle
Dies funktionierte wunderbar mit dem Zusatz "else yourVC.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;" Im Test von deviceVersion funktioniert es also weiterhin in iOS6.
LavaSlider
Dies sollte die akzeptierte Antwort sein. Funktioniert perfekt. Mein einziger Vorschlag wäre, diesen Code in eine separate Klasse zu stellen, die Sie dann in jedem View Controller verwenden können.
mluisbrown
3
Überprüfen Sie nicht die Systemversion, sondern prüfen Sie, ob die Methode verfügbar ist:if ([yourVC respondsToSelector:@selector(setTransitioningDelegate:)] { [yourVC setTransitioningDelegate:yourVC]; }
rckoenes
Großartig, es funktioniert. Ich musste den Delegaten nur auf "viewwillappear" setzen, da einige meiner Ansichten über den Storyboard-Editor definierte Segmente haben.
Imran
Lustigerweise kann die Rückkehr von diesem Übergang unter iOS 8 zu einem dauerhaften weißen Bildschirm führen. Natürlich müssen Sie dies unter iOS 8 nicht tun, da der Fehler, der dies erforderlich machte, behoben wurde.
user564904
9

Dies scheint ein UIKit-Fehler zu sein. Die folgende Problemumgehung scheint das Problem für mich zu lösen.

presentViewController (Platzieren Sie dies in dem Ansichts-Controller, zu dem Sie wechseln):

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

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

dismissViewControllerAnimated (Platzieren Sie dies in dem View Controller, den Sie schließen):

- (void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];

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

wenn Sie nicht verwenden autolayout. Sie müssen dies dem Ansichts-Controller hinzufügen, zu dem Sie dismiss:

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

    [self.view setNeedsLayout];
} 
Hugo
quelle
Entschuldigung, ich habe beim letzten Mal falschen Code eingefügt. Dieser Code hat bei mir funktioniert.
Hugo
Das hat in meinem Fall definitiv funktioniert. Storyboard Screenshot: cl.ly/image/060t10100b2W
Roger
Ich kann bestätigen, dass dies auch bei mir funktioniert hat. iOS 7.1.1
AlBeebe
3

Ich hatte das gleiche Problem und konnte es "lösen" (es ist keine echte Lösung für das Problem, aber es sieht gut aus :)). Der Trick besteht darin, dass der Ansichts-Controller mit pushViewController/popViewController mit einer UIViewAnimation einen Flip ausführt. Hier ist ein Beispielcode zur Darstellung des View Controllers:

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

Um es zu entlassen:

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

Wenn Sie nicht möchten, dass der navigationBarauf dem Push-Controller ist, rufen Sie einfach [self.navigationController setNavigationBarHidden:YES animated:NO]an viewWillAppear. Ich hoffe, dieser Ansatz hilft Ihnen.

RemeR
quelle
1
Dies löst tatsächlich das Problem beider Seiten des Übergangs, was in der obigen Antwort nicht der Fall ist. Wenn Sie eine Navigationsleiste auf dem Modal Controller haben, müssen Sie möglicherweise die linke Leistenschaltfläche auf Null setzen, um den genauen Effekt zu erzielen, den Sie unter iOS6 hatten (keine Zurück-Schaltfläche), aber das war es auch schon.
Entropie
1
Aus irgendeinem Grund führt diese Methode übrigens zu visuellen Störungen in der Navigationsleiste (wenn auch nicht so schwerwiegend wie bei Nichtverwendung). Hauptsächlich werden der Titel und der Text der Zurück-Schaltfläche erst nach dem Übergang angezeigt und sind währenddessen leer.
Entropie
Dies sollte die akzeptierte Antwort sein, es ist eine perfekte Problemumgehung für den Übergang in beide Richtungen. Aktivieren Sie einfach die Option zum Ausblenden der unteren Leiste beim Drücken und Ausblenden / Einblenden der Navigationsleiste, wenn dies in der Ansicht angezeigt wird.
Raladdin
1

Sowohl für den präsentierenden als auch für den präsentierten Ansichts-Controller habe ich einen UITableViewControllerInnenbereich UINavigationController, der beide mithilfe des automatischen Layouts konfiguriert wurde. Ich bemerkte, dass die anderen Antworten das Problem nicht lösten, dass beim Schließen der tableView des präsentierenden View-Controllers 20 pt vertikal springt.

Diese Lösung behebt dieses Problem.

In der vorgestellten Ansichtssteuerung (wie von Ben Packard vorgeschlagen):

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

In der darstellenden Ansichtssteuerung (wie teilweise von staubig vorgeschlagen):

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

Das gleiche für mich. Was tatsächlich funktioniert hat, ist, den Stil in CoverVertical zu ändern, sieht viel flüssiger aus.

Titicaca
quelle