2010-05-14 6 views
7

Meine App hat ungefähr 10 verschiedene UIViewControllers, von denen ich nur in den Landscape-Modus wechseln möchte, wenn das Gerät gedreht wird. (Den ganzen Rest möchte ich im Hochformat behalten.)Wie wird die UIViewController-Rotation als Reaktion auf Orientierungsänderungen implementiert?

Um Rotation auf dieser einen Ansicht zu implementieren, musste ich die 'shouldAutorotate'-Methode des Controllers implementieren und YES zurückgeben. Da auf diese Ansicht über einen Navigationscontroller zugegriffen wird, musste ich auch eine Unterklasse von UINavigationController erstellen, die 'shouldAutorotate' implementiert und YES zurückgibt.

Diese Lösung funktioniert, aber zu gut. Ich finde, dass alle UIViewControllers, die ich auf meine Unterklasse von UINavigationController stoße, auf Rotation reagieren, selbst wenn ich 'shouldAutorotate' implementiere und NO zurückgebe. (Denken Sie daran: Ich möchte nur, dass ein bestimmter UIViewController auf Rotation reagiert, nicht alle im Stack des Navigations-Controllers.)

Also meine Frage ist: Wie mache ich das am besten? Alle Lösungen, die ich mir vorstellen kann, scheinen 1) umständlich und 2) schlimmer, scheinen nicht zu funktionieren.

Vielen Dank.

Antwort

0

Ich habe Beispiele in der Art und Weise gesehen, wie Sie es tun, aber es konnte nicht richtig funktionieren. Ich fand den besseren Weg, es von Apple Beispielen zu tun. Im Wesentlichen implementieren Sie einen presentModalViewController und erstellen eine andere Ansicht. UIKit führt eine grundlegende Rotationsanimation durch und blendet zwischen der Ansicht aus. Sie müssen die gedrehte Ansicht als eine Delegatklasse implementieren, damit sie ihre aufrufende Klasse aufrufen kann, um sie zu verwerfen und die Ausrichtung zu aktualisieren.

- (void)orientationChanged:(NSNotification *)notification 
{ 
    // We must add a delay here, otherwise we'll swap in the new view 
    // too quickly and we'll get an animation glitch 
    NSLog(@"orientationChanged"); 
    [self performSelector:@selector(updateLandscapeView) withObject:nil afterDelay:0]; 
} 

Und dann eine Landschaft Bildschirm anzuzeigen:

- (void)updateLandscapeView 
{ 
PortraitView *portraitView = [[PortraitView alloc] init]; 
portraitView.delegate = self; 
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation; 
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView) 
{ 
    [self presentModalViewController: portraitView animated:YES]; 
    isShowingLandscapeView = YES; 
    } 
else if (deviceOrientation == UIDeviceOrientationPortrait && isShowingLandscapeView) 
{ 
    [self dismissModalViewControllerAnimated:YES]; 
    isShowingLandscapeView = NO; 
    } 
[portraitView release]; 
} 
1

ich dies tun, indem Sie einen Root-View-Controller mit (dies ein UITabBarController sein könnte) und in seinem viewDidLoad Methode i Rotation Ereignisse abonnieren:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(didRotate:) 
                 name:@"UIDeviceOrientationDidChangeNotification" 
                 object:nil]; 

Dann in der didRotate: Methode i look, bei der view-Controller sichtbar ist, wenn die Drehung passiert ist, und welche Ausrichtung das Telefon in:

- (void) didRotate:(NSNotification *)notification { 
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; 

/* 
    DEVICE JUST ROTATED TO PORTRAIT MODE 

orientation == UIDeviceOrientationFaceUp || 
orientation == UIDeviceOrientationFaceDown 

*/ 
if(orientation == UIDeviceOrientationPortrait) { 





/* 
    DEVICE JUST ROTATED TO LANDSCAPE MODE 
*/ 
}else if(orientation == UIInterfaceOrientationLandscapeLeft || 
     orientation == UIInterfaceOrientationLandscapeRight) { 






} 

} 

Innerhalb dieser didRotate: Sie können sehen, was ist der sichtbare ViewController und tun, was Sie von dort wollen.

Ich präsentiere einen Modal-View-Controller im Querformat, wenn ein bestimmter View-Controller sichtbar ist und das Telefon in Querformat gedreht wird. Wenn ein anderer View-Controller sichtbar ist, ignoriere ich das Ereignis.

Ich erzwinge, dass mein Modalansicht-Controller im Landscape-Modus in seiner ViewWillAppear-Methode angezeigt wird - ich kann jedem diesen Code geben, wenn er es möchte.

Hoffe, das hilft.

Dave

1

Returns YES auf der Navigations-Controller Unterklasse nur dann, wenn [[NavController topViewController] isKindOfClass: [RotatingViewController Klasse]]

2

wenn Sie UINavigationController implementieren, diese Klasse Ihr die Eltern ist, die steuert, Alle Kinder ViewControllers, die in den Stapel geschoben werden.Daher ist der RootViewController der einzige Controller, der Ja oder Nein zur Autorotation sagt. Auch wenn Sie bei Kindersichtsteuerungen Ja zur Autorotation weitergeben, zählen sie nicht!

Dies ist die Natur von UINavigationController. Um es zu ändern, haben Sie zwei Möglichkeiten:

1- Manuell manipulieren, was erfordert, dass Sie einige umständliche Codes durchlaufen.

2- Ändern Sie Ihr Design, damit es besser mit UINavigationController kompatibel ist. Diese einzelne Ansicht, die sich drehen sollte, sollte vom RootViewController aufgerufen werden (nicht vom Navigation Root View Controller - sie sind gleich benannt, aber völlig unterschiedlich), die Ansicht, die NavController hostet. Und wenn sich das Gerät dreht, wird der NavController entweder zur Ansicht oder zur anderen bewegt.

3- Die andere Methode, die auch funktioniert, aber nicht empfohlen wird, weil es das Konzept von MVC verletzt, ist, dass Ihr NavController auf Benachrichtigungen hören kann. Diese bestimmte Kindansicht, die CAN und SOLL drehen kann, kann eine Benachrichtigung - z.B. rotateMe, und sobald der NavController es hört, dreht es sich.

Wie gesagt, es wird funktionieren, aber es verstößt gegen das MVC-Modell - das ist in Ordnung für Apple, aber aus Programmiersicht ist nicht zu empfehlen.

Wenn Sie eine weitere Erklärung über beide benötigen, lassen Sie es mich bitte wissen.

Verwandte Themen