[Ios] Eine UIView-Animation abbrechen?


Answers

Benutzen:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];
Question

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.




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;
                     }
                 }];
}



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.




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.




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.




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;