iOS: Wie animiert man zu einer neuen Autolayout-Einschränkung (Höhe)?

123

Ich habe noch nie mit Autolayout- Einschränkungen gearbeitet. Ich habe eine kleine neue App, an der ich arbeite, und habe festgestellt, dass die Ansichten der NIB standardmäßig auf Autolayout eingestellt sind. Also, ich dachte ich die Möglichkeit zur Arbeit nehmen würde mit ihm und versuchen Sie herauszufinden, wo Apple mit diesem geht.

Erste Herausforderung:

Ich muss die Größe eines MKMapView ändern und möchte es an der neuen Position animieren. Wenn ich das so mache, wie ich es gewohnt bin:

[UIView animateWithDuration:1.2f
     animations:^{
         CGRect theFrame = worldView.frame;
         CGRect newFrame = CGRectMake(theFrame.origin.x, theFrame.origin.y, theFrame.size.width, theFrame.size.height - 170);
         worldView.frame = newFrame;
}];

... dann wird die MKMapView bei jeder Aktualisierung einer Geschwisteransicht auf ihre ursprüngliche Höhe zurückschnappen (in meinem Fall wird der Titel eines UISegmentedControl aktualisiert [myUISegmentedControl setTitle:newTitle forSegmentAtIndex:0]).

Ich denke also, ich möchte die Einschränkungen von MKMapView so ändern, dass sie der Höhe der übergeordneten Ansicht entsprechen und relativ zum oberen Rand des UISegmentedControl sind, das abgedeckt wurde :V:[MKMapView]-(16)-[UISegmentedControl]

Ich möchte, dass die MKMapView-Höhe verkürzt wird, sodass einige Steuerelemente unter der Kartenansicht angezeigt werden. Um dies zu tun Ich denke , ich brauche die Einschränkung von einem festen in voller Größe im Hinblick auf eine ändern , wo der Boden auf die Spitze eines UISegmentedControl beschränkt ist ... und ich möchte es als Ansicht schrumpft auf neue Größe animieren.

Wie geht man damit um?

Bearbeiten - Diese Animation wird nicht animiert, obwohl der untere Rand der Ansicht sofort nach oben verschoben wird:

    [UIView animateWithDuration:1.2f
         animations:^{
             self.nibMapViewConstraint.constant = -170;

    }];

und das nibMapViewConstraintist in IB mit der unteren Vertikalraumbeschränkung verbunden.

Meltemi
quelle
1
Ich weiß, dass Sie den konstanten Wert der Einschränkung in einem Block [UIView animateWithDuration ..] leicht ändern können, um die Höhenänderung zu animieren. Sie müssen ein IBOutlet für diese Einschränkung erstellen und es in Ihre xib einbinden oder auf andere Weise einen Verweis darauf behalten, wenn Sie es im Code erstellt haben (oder alle Einschränkungen durchlaufen, um danach zu suchen). Ich bin mir nicht sicher, wie ich verwandte Änderungen animieren soll, aber ich habe gelesen, dass Sie nur konstante und nicht andere Werte einer Einschränkung ändern sollten (für andere Werte erstellen Sie eine neue Einschränkung).
Yuf
Hmm. dachte ich könnte es, aber ich bin es nicht animierend. Es ändert sich erfolgreich und befindet sich im Animationsblock, wird aber nicht animiert!?!
Meltemi
Ich habe meine Antwort hier gefunden: < stackoverflow.com/questions/12926566/… >
Meltemi
1
Vergiss nicht das [view layoutIfNeeded], das war auch mein Problem, haha. Das ist die gleiche Frage, die mein Problem gelöst hat.
Yuf
Mögliches Duplikat von Wie animiere ich Einschränkungsänderungen?
Sinnvoller

Antworten:

179

Nach dem Aktualisieren Ihrer Einschränkung:

[UIView animateWithDuration:0.5 animations:^{[self.view layoutIfNeeded];}];

Durch self.vieweinen Verweis auf die enthaltene Ansicht ersetzen .

Ed McManus
quelle
4
Dies funktioniert für die Ansicht selbst. Die Ansichten, für die Einschränkungen für diese Ansicht gelten, werden jedoch sofort verschoben. Was mache ich? ty
dietbacon
7
Sie müssen das Layout bei Bedarf auch in diesen Ansichten aufrufen. Es funktioniert jedoch nicht richtig, da dies auch die Aktualisierung der Ansicht animiert. Wie animieren Sie die Einschränkungsanpassung nur in den anderen Ansichten?
ngb
3
Achtung: Bei Verwendung des UIViewAnimationOptionBeginFromCurrentStateLayouts werden die Einschränkungen VOR der Animation festgelegt!
Robert
12
Anstatt layoutIfNeededfür jede dieser Ansichten aufzurufen, rufen [[self.view superview] layoutIfNeeded];
Sie
2
@ngb Sie müssen die Einschränkungskonstante innerhalb des Animationsblocks ändern . Auf diese Weise ändert sich die Einschränkung mit der Animation und Sie können sie weiter verwenden UIViewAnimationOptionBeginFromCurrentState.
Eran Goldin
86

Dies funktioniert bei mir (sowohl iOS7 als auch iOS8 +). Klicken Sie auf die automatische Layoutbeschränkung, die Sie anpassen möchten (im Interface Builder, z. B. obere Einschränkung). Machen Sie dies als nächstes zu einem IBOutlet.

@property (strong, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;

Nach oben animieren;

    self.topConstraint.constant = -100;    
    [self.viewToAnimate setNeedsUpdateConstraints]; 
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded]; 
    }];

Animieren Sie zurück zum ursprünglichen Ort

    self.topConstraint.constant = 0;    
    [self.viewToAnimate setNeedsUpdateConstraints];  
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded];
    }];
DevC
quelle
2
BEEINDRUCKEND!! Das funktioniert wirklich! Diese Antwort hat mir die Augen geöffnet. Vielen Dank! - Erik
Erik van der Neut
2
@ErikvanderNeut es war auch für mich, froh, dass es hilfreich war. Ich werde von nun an eher Einschränkungen als die Frame-Position animieren.
DevC
Verpassen Sie nicht hinzuzufügen: [containerView layoutIfNeeded]; Es stellt sicher, dass alle ausstehenden Layoutvorgänge VOR dem animateWithDuration-Block abgeschlossen wurden.
Ingconti
11

Es gibt ein sehr gutes Tutorial von Apple selbst, das erklärt, wie man Animationen mit Autolayout verwendet. Folgen Sie diesem Link und suchen Sie das Video mit dem Namen "Automatisches Layout anhand eines Beispiels". Es enthält einige interessante Informationen zum automatischen Layout und im letzten Teil geht es um die Verwendung von Animationen.

Glenn
quelle
1

Die meisten Benutzer verwenden Autolayout, um Elemente in ihren Ansichten zu gestalten und die Layoutbeschränkungen zu ändern, um Animationen zu erstellen.

Eine einfache Möglichkeit, dies ohne viel Code zu tun, besteht darin, die UIView zu erstellen, die Sie im Storyboard animieren möchten, und anschließend eine versteckte UIView zu erstellen, in der die UIView enden soll. Sie können die Vorschau in xcode verwenden, um sicherzustellen, dass beide UIViews dort sind, wo Sie sie haben möchten. Blenden Sie danach die End-UIView aus und tauschen Sie die Layout-Einschränkungen aus.

Es gibt eine Poddatei zum Austauschen von Layoutbeschränkungen namens SBP, wenn Sie sie nicht selbst schreiben möchten.

Hier ist ein Tutorial .

Arjay Waran
quelle
0

Sie müssen nicht mehr IBOutlet referencevon der Einschränkung verwenden, stattdessen können Sie die Einschränkung direkt accessoder updatebereits anwenden, entweder von Programmaticallyoder aus einer Interface Builderbeliebigen Ansicht mithilfe der KVConstraintExtensionsMasterBibliothek. Diese Bibliothek verwaltet auch das CumulativeVerhalten von NSLayoutConstraint.

So fügen Sie in containerView eine Höhenbeschränkung hinzu

 CGFloat height = 200;
 [self.containerView applyHeightConstrain:height];

So aktualisieren Sie die Höhenbeschränkung von containerView mit Animation

[self.containerView accessAppliedConstraintByAttribute:NSLayoutAttributeHeight completion:^(NSLayoutConstraint *expectedConstraint){
        if (expectedConstraint) {
            expectedConstraint.constant = 100;

            /* for the animation */ 
            [self.containerView  updateModifyConstraintsWithAnimation:NULL];
      }
    }];
keshav vishwkarma
quelle