ios - Eine UIView-Animation abbrechen?


Ist es möglich, eine UIView Animation während der UIView abzubrechen? Oder müsste ich auf das CA-Level fallen?

Dh ich habe so etwas gemacht (vielleicht auch eine Ende-Animation Aktion):

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties

// set view properties

[UIView commitAnimations];

Aber bevor die Animation abgeschlossen ist und ich die Animation beendet habe, möchte ich sie abbrechen (cut it short). Ist das möglich? Wenn man sich umschaut, findet man ein paar Leute, die dieselbe Frage ohne Antworten stellen - und ein oder zwei Leute spekulieren, dass es nicht geht.



Answers



So wie ich es mache, erstellen wir eine neue Animation zu Ihrem Endpunkt. +setAnimationBeginsFromCurrentState: Sie eine sehr kurze Dauer fest und stellen Sie sicher, dass Sie die +setAnimationBeginsFromCurrentState: -Methode verwenden, um mit dem aktuellen Status zu beginnen. Wenn Sie YES wählen, wird die aktuelle Animation abgeschnitten. Sieht ungefähr so ​​aus:

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.1];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties

// set view properties

[UIView commitAnimations];



Benutzen:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];



Der einfachste Weg, um alle Animationen für eine bestimmte Ansicht sofort anzuhalten, ist folgende:

Verknüpfen Sie das Projekt mit QuartzCore.framework. Am Anfang des Codes:

#import <QuartzCore/QuartzCore.h>

Jetzt, wenn Sie alle Animationen auf einer Ansicht stoppen möchten, die in ihren Spuren tot ist, sagen Sie dies:

[CATransaction begin];
[theView.layer removeAllAnimations];
[CATransaction commit];

Die Mittellinie würde von alleine funktionieren, aber es gibt eine Verzögerung, bis der Runloop endet (der "Neuzeichnungsmoment"). Um diese Verzögerung zu vermeiden, schließen Sie den Befehl wie gezeigt in einen expliziten Transaktionsblock ein. Dies funktioniert, vorausgesetzt, es wurden keine anderen Änderungen an dieser Schicht in der aktuellen Laufschleife durchgeführt.




Verwenden Sie bei iOS 4 und höher die Option UIViewAnimationOptionBeginFromCurrentState in der zweiten Animation, um den ersten Animations- UIViewAnimationOptionBeginFromCurrentState zu schneiden.

Nehmen wir als Beispiel an, Sie haben eine Sicht mit einem Aktivitätsindikator. Sie möchten die Aktivitätsanzeige einblenden, während eine potenziell zeitaufwendige Aktivität beginnt, und sie ausklappen, wenn die Aktivität beendet ist. Im folgenden Code heißt die Ansicht mit dem Aktivitätsindikator activityView .

- (void)showActivityIndicator {
    activityView.alpha = 0.0;
    activityView.hidden = NO;
    [UIView animateWithDuration:0.5
                 animations:^(void) {
                     activityView.alpha = 1.0;
                 }];

- (void)hideActivityIndicator {
    [UIView animateWithDuration:0.5
                 delay:0 options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^(void) {
                     activityView.alpha = 0.0;
                 }
                 completion:^(BOOL completed) {
                     if (completed) {
                         activityView.hidden = YES;
                     }
                 }];
}



Um eine Animation abzubrechen, müssen Sie die Eigenschaft, die gerade animiert wird, außerhalb der UIView-Animation festlegen. Das stoppt die Animation, wo immer sie ist, und die UIView springt zu der Einstellung, die Sie gerade definiert haben.




Wenn Sie eine Einschränkung animieren, indem Sie die Konstante anstelle einer Ansichtseigenschaft ändern, funktioniert keine der anderen Methoden unter iOS 8.

Beispielanimation:

self.constraint.constant = 0;
[self.view updateConstraintsIfNeeded];
[self.view layoutIfNeeded];
[UIView animateWithDuration:1.0f
                      delay:0.0f
                    options:UIViewAnimationOptionCurveLinear
                 animations:^{
                     self.constraint.constant = 1.0f;
                     [self.view layoutIfNeeded];
                 } completion:^(BOOL finished) {

                 }];

Lösung:

Sie müssen die Animationen aus den Layern aller Ansichten entfernen, die von der Constraint-Änderung und ihren Sublayern betroffen sind.

[self.constraintView.layer removeAllAnimations];
for (CALayer *l in self.constraintView.layer.sublayers)
{
    [l removeAllAnimations];
}






Nichts davon hat es für mich gelöst, aber das hat geholfen: Die UIView Animation legt die Eigenschaft sofort fest und animiert sie dann. Sie stoppt die Animation, wenn die Präsentationsebene mit dem Modell übereinstimmt (die Eigenschaft set).

Ich löste mein Problem, das lautete: "Ich möchte animieren, wo Sie aussehen, wie Sie erscheinen" ("Sie" bedeutet die Ansicht). Wenn du DAS willst, dann:

  1. Fügen Sie QuartzCore hinzu.
  2. CALayer * pLayer = theView.layer.presentationLayer;

die Position auf die Präsentationsschicht setzen

Ich benutze ein paar Optionen, einschließlich UIViewAnimationOptionOverrideInheritedDuration

Da die Dokumentation von Apple jedoch vage ist, weiß ich nicht, ob sie die anderen Animationen wirklich außer Kraft setzt, wenn sie verwendet wird, oder nur Timer zurücksetzt.

[UIView animateWithDuration:blah... 
                    options: UIViewAnimationOptionBeginFromCurrentState ... 
                    animations: ^ {
                                   theView.center = CGPointMake( pLayer.position.x + YOUR_ANIMATION_OFFSET, pLayer.position.y + ANOTHER_ANIMATION_OFFSET);
                   //this only works for translating, but you get the idea if you wanna flip and scale it. 
                   } completion: ^(BOOL complete) {}];

Und das sollte vorerst eine gute Lösung sein.




[UIView setAnimationsEnabled:NO];
// your code here
[UIView setAnimationsEnabled:YES];



Ich habe das gleiche Problem; Die APIs haben nichts, um bestimmte Animationen zu löschen. Das

+ (void)setAnimationsEnabled:(BOOL)enabled

deaktiviert ALLE Animationen und funktioniert somit nicht für mich. Es gibt zwei Lösungen:

1) Machen Sie Ihr animiertes Objekt zu einer Unteransicht. Wenn Sie die Animationen für diese Ansicht abbrechen möchten, entfernen Sie die Ansicht oder blenden Sie sie aus. Sehr einfach, aber Sie müssen die Unteransicht ohne Animationen neu erstellen, wenn Sie sie im Blick behalten müssen.

2) Wiederhole den anim nur einen und mache einen delegate selector, um den anim neu zu starten.

-(void) startAnimation {
NSLog(@"startAnim alpha:%f", self.alpha);
[self setAlpha:1.0];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(pulseAnimationDidStop:finished:context:)];
[self setAlpha:0.1];
[UIView commitAnimations];
}

- (void)pulseAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
if(hasFocus) {
    [self startAnimation];
} else {
    self.alpha = 1.0;
}
}

-(void) setHasFocus:(BOOL)_hasFocus {
hasFocus = _hasFocus;
if(hasFocus) {
    [self startAnimation];
}
}

Problem mit 2) ist, dass es immer eine Verzögerung gibt, die den anim stoppt, wenn er den aktuellen Animationszyklus beendet.

Hoffe das hilft.




Es tut uns leid, diese Antwort wiederzubeleben, aber in iOS 10 hat sich etwas geändert, und jetzt ist das Abbrechen möglich und Sie können sogar anständig abbrechen!

Nach iOS 10 können Sie Animationen mit UIViewPropertyAnimator abbrechen !

UIViewPropertyAnimator(duration: 2, dampingRatio: 0.4, animations: {
    view.backgroundColor = .blue
})
animator.stopAnimation(true)

Wenn Sie true übergeben, bricht es die Animation ab und stoppt genau dort, wo Sie es abgebrochen haben. Die Abschlussmethode wird nicht aufgerufen. Wenn Sie jedoch false übergeben, sind Sie für die Fertigstellung der Animation verantwortlich:

animator.finishAnimation(.start)

Sie können Ihre Animation beenden und im aktuellen Zustand bleiben (.current) oder in den Ausgangszustand (.start) oder in den Endzustand (.end) wechseln

Übrigens können Sie sogar später pausieren und neu starten ...

animator.pauseAnimation()
animator.startAnimation()

Hinweis: Wenn Sie keinen abrupten Abbruch wünschen, können Sie Ihre Animation umkehren oder sogar Ihre Animation ändern, nachdem Sie sie angehalten haben!




Selbst wenn Sie die Animation auf die oben beschriebene Weise abbrechen, wird der didStopSelector noch ausgeführt. Wenn Sie also in Ihrer Anwendung durch Animationen gesteuerte Logikzustände haben, werden Sie Probleme haben. Aus diesem Grund benutze ich mit den oben beschriebenen Möglichkeiten die Kontextvariable von UIView Animationen. Wenn Sie den aktuellen Status Ihres Programms über den Context-Parameter an die Animation übergeben, entscheidet Ihre didStopSelector Funktion beim Anhalten der Animation, ob sie etwas tun soll oder nur basierend auf dem aktuellen Status und dem als Kontext übergebenen didStopSelector zurückkehren soll.




CALayer * pLayer = self.layer.presentationLayer;
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView animateWithDuration:0.001 animations:^{
    self.frame = pLayer.frame;
}];



So halten Sie eine Animation an, ohne den Status auf original oder final zurückzusetzen:

CFTimeInterval paused_time = [myView.layer convertTime:CACurrentMediaTime() fromLayer:nil];
myView.layer.speed = 0.0;
myView.layer.timeOffset = paused_time;