webentwicklung-frage-antwort-db.com.de

Kann ich mit Autolayout verschiedene Einschränkungen für Quer- und Hochformat festlegen?

Ist es möglich, die Einschränkungen zu ändern, wenn das Gerät gedreht wird? Wie könnte dies erreicht werden?

Ein einfaches Beispiel könnten zwei Bilder sein, die im Hochformat übereinander gestapelt sind, im Querformat jedoch nebeneinander liegen.

Wenn dies nicht möglich ist, wie kann ich dieses Layout sonst ausführen?

Ich konstruiere meine Ansichten und Einschränkungen im Code und benutze keinen Interface Builder.

47
Ben Packard

Bearbeiten: Mit dem neuen Konzept von Größenklassen , das in Xcode 6 eingeführt wurde, können Sie Einfaches Einrichten verschiedener Einschränkungen für bestimmte Größenklassen in Interface Builder. Die meisten Geräte (z. B. alle aktuellen iPhones) haben im Querformat eine vertikale Größenklasse Kompakt.

Dies ist ein viel besseres Konzept für allgemeine Layoutentscheidungen als die Bestimmung der Ausrichtung des Geräts.

Das heißt, wenn Sie die Ausrichtung wirklich kennen müssen, ist UIDevice.currentDevice().orientation der richtige Weg.


Ursprünglicher Beitrag:

Überschreiben Sie die updateViewConstraints -Methode von UIViewController, um Layoutbeschränkungen für bestimmte Situationen bereitzustellen. Auf diese Weise wird das Layout immer situationsgerecht eingerichtet. Stellen Sie sicher, dass sie mit den im Storyboard erstellten Einschränkungen einen vollständigen Satz bilden. Sie können IB verwenden, um Ihre allgemeinen Einschränkungen einzurichten und die zu ändernden Elemente zur Laufzeit zu entfernen.

Ich verwende die folgende Implementierung, um für jede Ausrichtung einen anderen Satz von Einschränkungen darzustellen:

-(void)updateViewConstraints {
    [super updateViewConstraints];

    // constraints for portrait orientation
    // use a property to change a constraint's constant and/or create constraints programmatically, e.g.:
    if (!self.layoutConstraintsPortrait) {
        UIView *image1 = self.image1;
        UIView *image2 = self.image2;
        self.layoutConstraintsPortrait = [[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy];
        [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem: image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
        [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    }

    // constraints for landscape orientation
    // make sure they don't conflict with and complement the existing constraints
    if (!self.layoutConstraintsLandscape) {
        UIView *image1 = self.image1;
        UIView *image2 = self.image2;
        self.layoutConstraintsLandscape = [[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy];
        [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
        [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem: image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    }

    BOOL isPortrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation);
    [self.view removeConstraints:isPortrait ? self.layoutConstraintsLandscape : self.layoutConstraintsPortrait];
    [self.view addConstraints:isPortrait ? self.layoutConstraintsPortrait : self.layoutConstraintsLandscape];        
}

Jetzt müssen Sie nur noch eine Einschränkungsaktualisierung auslösen, wenn sich die Situation ändert. Überschreiben Sie willAnimateRotationToInterfaceOrientation:duration:, Um die Aktualisierung der Einschränkung bei Orientierungsänderungen zu animieren:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];

    [self.view setNeedsUpdateConstraints];

}
39
knl

Der Ansatz, den ich verwende (zum Guten oder Schlechten), besteht darin, beide Abhängigkeiten (Hoch- und Querformat) im Storyboard-Editor zu definieren.

Um die Storyboard-Warnungen der Hölle zu vermeiden, setze ich alle Sets auf eine Priorität von 999, damit sie nicht überall rot angezeigt werden.

Dann füge ich alle Einschränkungen zu Outlet-Sammlungen hinzu:

@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *portraitConstraints;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *landscapeConstraints;

Schließlich implementiere ich die ViewControllers -Methode meines viewWillLayout:

- (void) viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    for (NSLayoutConstraint *constraint in self.portraitConstraints) {
        constraint.active = (UIApplication.sharedApplication.statusBarOrientation == UIDeviceOrientationPortrait);
    }
    for (NSLayoutConstraint *constraint in self.landscapeConstraints) {
        constraint.active = (UIApplication.sharedApplication.statusBarOrientation != UIDeviceOrientationPortrait);
    }
}

Das scheint zu funktionieren. Ich wirklich wünschte, Sie könnten die standardmäßige aktive Eigenschaft im Storyboard-Editor festlegen.

17
Travis Griggs

Ich verfolge den gleichen Ansatz wie Sie (keine NIB-Dateien oder Storyboards). Sie müssen Ihre Einschränkungen in der updateViewConstraints -Methode aktualisieren (indem Sie die Geräteorientierung überprüfen). Es ist nicht erforderlich, setNeedsUpdateConstraints in updateViewConstraints aufzurufen, da die letzte Methode automatisch aufgerufen wird, sobald Sie die Geräteorientierung ändern.

2
rokridi

Sie können Ihre Abhängigkeiten in einer Eigenschaft oder Variablen als Hoch- und Querformatversion speichern und dann beim Drehen festlegen und entfernen.

Ich habe dies getan, um meine Einschränkungen in xib für die anfängliche Ansicht zu definieren und sie den Ausgängen im Ansichtscontroller zuzuweisen. Beim Drehen erstelle ich die alternativen Rückhaltevorrichtungen, entferne die Auslässe, behalte sie aber bei und setze die alternativen ein.

Kehren Sie den Vorgang beim Zurückdrehen um.

0
Dean Davids