Frage

Ich habe eine verschachtelte Ansichtshierarchie für eine iPad -Anwendung, die Orientierungsänderungen unterstützt. Es sieht folgendermaßen ähnlich aus.

UIViewController
    UIView
        - UIView
            - UIImageView (disable rotation)
            - UIImageView
            - UIView (disable rotation)
        - UIView
        - UIView
        ...

Ich möchte die Orientierung für einige meiner Unteransichten sperren, während andere automatisch rotieren und die Größe ändern können. Ich kann nicht ganz herausfinden, wie ich das erreichen kann.

Ein Ansatz scheint die Unteransicht manuell innerhalb des Inneren zu drehen willAnimateRotationToInterfaceOrientation:. Das ist nicht besonders attraktiv, da der SDK eine Rotation ausführt, die ich einfach rückgängig machen würde.

Gibt es eine Möglichkeit, Ausrichtungsänderungen für Unteransichten oder eine andere Methode zur Umstrukturierung meiner Hierarchie einfach zu deaktivieren?

War es hilfreich?

Lösung

Die Autorotation wird von einem UiviewController einer Ansicht (der Ansicht gehandhabt (shouldAutorotateToInterfaceOrientation:), ein Ansatz besteht darin, Ihre Hierarchie so zu ordnen, dass rotierbare Ansichten von einem Ansichtsregler und nicht rotatierbaren Ansichten von einem anderen Ansichtsregler verwaltet werden. Beide Root -Ansichten von UIViewController müssen dann zum Fenster/zum Überblick hinzufügen.

Die Subtilität hier ist, dass, wenn Sie zwei Ansichten des Ansichtscontrollers auf derselben Ebene haben (dh durch hinzugefügte via addSubview:) nur der erste Ansichtsregler (normalerweise das Fenster des Fensters rootViewController) wird die erhalten shouldAutorotateToInterfaceOrientation: Botschaft.

Ich habe diesen Ansatz selbst verwendet, um eine Symbolleiste zu erreichen, die sich dreht, während die Hauptansicht nicht der Fall ist.

Apples technischer Q & A -QA1688 ("Warum wird mein UIViewController nicht mit dem Gerät gedreht?") spricht ein wenig über dieses Problem.


Update für iOS 6:

Autorotation verwendet jetzt UIViewController's shouldAutorotate und supportedInterfaceOrientations Methoden. shouldAutorotate kehrt zurück YES standardmäßig, aber denken Sie daran, dass ein anderer Ansichtskontroller als der rootViewController Wessen Ansicht ist eine direkte Unteransicht des Fensters sowie ohnehin keine Rotationsaufrufe.


Beispielcode für iOS 6:

Erstellen Sie ein neues Projekt mit der Vorlage "Einzelanwendungsanwendung" und stellen Sie sicher, dass "Storyboards verwenden" überprüft wird. Wir werden das bereitgestellte verwenden ViewController Klasse als rotierender Ansichtscontroller (benennen Sie ihn um, wenn Sie möchten!) Und erstellen Sie eine Sekunde UIViewController Unterklasse angerufen NonRotatingViewController. Obwohl dieser Ansichtscontroller die Rotationsrückrufe nie empfangen wird, fügen Sie für Vollständigkeit und Klarheit den folgenden Code in hinzu NonRotatingViewController.m:

- (BOOL)shouldAutorotate
{
    return NO;
}

In dem MainStoryboard Datei, ziehen Sie ein neues Ansichts -Controller -Objekt heraus und setzen Sie seine Klasse auf NonRotatingViewController, und setzen Sie seine Storyboard -ID auf "nicht zurottenvc". Ändern Sie während der gesamten Hintergrundfarbe der rotierenden Ansicht der rotierenden Ansicht der rotierenden Ansicht (die nicht rotierende Ansicht wird darunter hinzugefügt) und fügen Sie jeder Ansicht ein Etikett hinzu. Im AppDelegate.m, Fügen Sie den folgenden Code hinzu:

#import "NonRotatingViewController.h"

// ...
// ...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    NonRotatingViewController *nonRotatingVC = [mainStoryboard instantiateViewControllerWithIdentifier:@"NonRotatingVC"];
    [self.window addSubview:nonRotatingVC.view];
    return YES;
}

Dies ist nur so ein nicht rotierender Ansichtsregler und füge seine Ansicht direkt zum Fenster hinzu (NB an diesem Punkt des Fensters rootViewController wurde bereits von der Storyboard festgelegt).

Führen Sie das Projekt aus. Drehen Sie das Gerät und staunen Sie beim Anblick eines Etiketts, während das andere still bleibt!


Beispielcode Pre iOS 6:

Ich habe dies in einem neuen Projekt gemacht - eine neue Ansichtsanwendung wird gut funktionieren. Fügen Sie zwei neue Ansichtsregler hinzu: RotatingViewController und NonRotatingViewController. In jeder ihrer Nibs habe ich gerade ein Etikett hinzugefügt, um zu beschreiben, ob sich die Ansicht drehen sollte oder nicht. Fügen Sie den folgenden Code hinzu:

'RotatingViewController.m'

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}


'NonRotatingViewController.m'

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    if (interfaceOrientation == UIInterfaceOrientationPortrait) {    // Or whatever orientation it will be presented in.
        return YES;
    }
    return NO;
}


'AppDelegate.m'

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    RotatingViewController *rotating = [[RotatingViewController alloc] initWithNibName:@"RotatingViewController" bundle:nil];
    self.rotatingViewController = rotating;
    [rotating release];

    NonRotatingViewController *nonRotating = [[NonRotatingViewController alloc] initWithNibName:@"NonRotatingViewController" bundle:nil];
    self.nonRotatingViewController = nonRotating;
    [nonRotating release];

    [self.window addSubview:self.rotatingViewController.view];
    [self.window insertSubview:self.nonRotatingViewController.view belowSubview:self.rotatingViewController.view];

    [self.window makeKeyAndVisible];

    return YES;
}

Ich hoffe das hilft.

Andere Tipps

Hier ist ein anderer Weg. Platzieren Sie diesen Code einfach in Ihre ViewController ViewDIDLOAD:

    YourAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
        // the view you don't want rotated (there could be a heierarchy of views here):
    UIView *nonRotatingView = [[UIView alloc] initWithFrame:CGRectMake(100,0,30,500)];
    nonRotatingView.backgroundColor = [UIColor purpleColor];

        // make sure self.view and its children are transparent so you can see through to this view that will not be rotated behind self.view.

    [delegate.window insertSubview:nonRotatingView  belowSubview:self.view];

        // you can't put it in the front using:
        //    [delegate.window insertSubview:nonRotatingView aboveSubview:self.view];
        // It will show up the same as before

    // you should declare nonRotatingView as a property so you can easily access it for removal, etc.

Mein Ansatz, dieses Problem zu lösen UINotification Um automatische Rotation zu erkennen und die Aussicht umgekehrt zu drehen.

Hier finden Sie den vollständigen Code:
https://gist.github.com/ffraenz/5945301

- (void)orientationDidChangeNotificationReceived:(NSNotification *)notification
{
    // find out needed compass rotation
    //  (as a countermeasure to auto rotation)
    float rotation = 0.0;

    if (self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
        rotation = M_PI;
    else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
        rotation = M_PI / 2.0;
    else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight)
        rotation = M_PI / (- 2.0);

    // rotate compass without auto rotation animation
    //  iOS rotation animation duration is 0.3
    //  this excludes the compassView from the auto rotation
    //  (same effect as in the camera app where controls do rotate and camera viewport don't)
    [UIView animateWithDuration:0.3 animations:^(void) {
        self.compassView.transform = CGAffineTransformMakeRotation(rotation);
    }];
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top