Frage

Ist es möglich, eine UIView Animation abzubrechen, während es im Gange ist? Oder habe ich auf die CA-Ebene fallen zu lassen?

d. Ich habe so etwas getan (vielleicht ein Ende Animation Aktion zu setzen):

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

// set view properties

[UIView commitAnimations];

Doch bevor die Animation abgeschlossen ist und ich erhalte die Animation beendet Ereignis, möchte ich es abbrechen (es kurz). Ist das möglich? um findet ein paar Leute googeln die gleiche Frage ohne Antwort zu fragen -. und ein oder zwei Leute spekulieren, dass es nicht getan werden kann,

War es hilfreich?

Lösung

So wie ich es tue, ist eine neue Animation zu Ihrem Endpunkt zu erstellen. Stellen Sie eine sehr kurze Dauer und stellen Sie sicher, dass Sie die +setAnimationBeginsFromCurrentState: Methode aus dem aktuellen Zustand zu starten. Wenn Sie es auf YES gesetzt, wird die aktuelle Animation kurz geschnitten. Sieht so etwas wie folgt aus:

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

// set view properties

[UIView commitAnimations];

Andere Tipps

Verwendung:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];

einfachste Weg zu stoppen alle Animationen auf einer bestimmten Ansicht, sofort , ist dies:

Verknüpfen Sie das Projekt QuartzCore.framework. Zu Beginn des Codes:

#import <QuartzCore/QuartzCore.h>

Wenn Sie nun alle Animationen auf einen Blick tot in ihren Tracks stoppen wollen, sagen diese:

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

Die mittlere Linie würde ganz von selbst funktionieren, aber es gibt eine Verzögerung, bis die Runloop beendet (die „neu zeichnet Moment“). Um diese Verzögerung zu vermeiden, wickelt den Befehl in einem expliziten Transaktionsblock, wie dargestellt. Dies funktioniert keine weiteren Änderungen zur Verfügung gestellt hat auf dieser Ebene im aktuellen Runloop durchgeführt wurde.

Auf iOS 4 und höher, verwenden, um die UIViewAnimationOptionBeginFromCurrentState Option auf der zweiten Animation die erste Animation kurz zu schneiden.

Als Beispiel annehmen, dass Sie eine Ansicht mit einem Aktivitätsindikator haben. Sie möchten in der Aktivitätsanzeige verblassen, während einige möglicherweise zeitraubend Aktivität beginnt, und verblassen es aus, wenn die Aktivität abgeschlossen ist. Im folgenden Code wird die Ansicht mit der Aktivitätsanzeige auf sie genannt 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;
                     }
                 }];
}

eine Animation abzubrechen müssen Sie einfach die Eigenschaft festzulegen, die zur Zeit animiert wird, außerhalb der UIView Animation. Das wird die Animation zu stoppen, wo immer es ist, und die UIView springt auf die Einstellung, die Sie gerade definiert haben.

Leider diese Antwort wieder zu beleben, aber in iOS 10 Dinge ein bisschen geändert, und jetzt Cancelling ist möglich, und Sie können sogar anmutig aufheben!

Nach dem iOS 10 Sie Animationen mit UIViewPropertyAnimator !

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

Wenn Sie einen echten Pass bricht es die Animation und hält dort, wo Sie es abgebrochen. Die Completion-Methode wird nicht aufgerufen werden. Wenn Sie jedoch falsch passieren sind Sie verantwortlich für die Ausrüstung der Animation:

animator.finishAnimation(.start)

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

Übrigens können Sie auch später anhalten und neu starten ...

animator.pauseAnimation()
animator.startAnimation()

Hinweis: Wenn Sie nicht wollen, eine abrupte Abbrechen Sie Ihre Animation rückgängig machen kann oder sogar Ihre Animation ändern, nachdem Sie anhalten

Wenn Sie eine Einschränkung animieren, indem die Konstante anstelle einer Ansicht Eigenschaft keine der anderen Methoden zu ändern arbeitet auf iOS 8.

Beispiel Animation:

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 Schichten aus irgendwelchen Ansichten entfernen, indem die Einschränkung ändern und ihre Unterschichten beeinflusst zu werden.

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

Wenn Sie wollen einfach nur Pause / Stopp-Animation glatt

self.yourView.layer.speed = 0;

Quelle: Wie die Animation einer Schicht Baum pausieren

Keine der oben gelöst es für mich, aber das half: Die UIView Animation die Eigenschaft sofort setzt, dann belebt es. Es stoppt die Animation, wenn die Präsentationsschicht zu dem Modell passt (die eingestellte Eigenschaft).

löste ich mein Problem, das war „ich animieren möchten, wo Sie sehen, wie Sie erscheinen“ ( ‚Sie‘ die Ansicht Bedeutung). Wenn Sie das wollen, dann:

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

legen Sie die Position an die Präsentationsschicht

Ich benutze ein paar Optionen, einschließlich UIViewAnimationOptionOverrideInheritedDuration

Aber weil Apples Dokumentation vage ist, weiß ich nicht, ob es wirklich die anderen Animationen überschreibt, wenn verwendet, oder einfach nur zurücksetzt Timer.

[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 eine anständige Lösung für jetzt sein.

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

Ich habe das gleiche Problem; die APIs haben nichts einige spezifische Animation abzubrechen. Das

+ (void)setAnimationsEnabled:(BOOL)enabled

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

1) machen Sie Ihre animierten Objekt ein Subview. Dann, wenn Sie die Animationen für diese Ansicht abbrechen möchten, entfernen Sie die Ansicht oder ausblenden. Sehr einfach, aber Sie müssen die subview ohne Animationen erstellen, wenn Sie es im Auge behalten müssen.

2) wiederholen Sie den anim nur einen, und einen Delegierten Wähler machen den anim neu zu starten, wenn nötig, wie folgt aus:

-(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 2) ist, dass es immer Verzögerung die Anim stoppen, wie es den aktuellen Animationszyklus beendet ist.

Hope, das hilft.

Auch wenn Sie die Animation auf den Wegen über Animation didStopSelector noch läuft abzubrechen. Also, wenn Sie logische Zustände in Ihrer Anwendung getrieben von Animationen haben Sie Probleme haben. Aus diesem Grunde mit den oben I beschriebenen Weisen verwenden, um die Kontextvariable von UIView Animationen. Wenn Sie den aktuellen Status Ihres Programms durch den Kontext param, um die Animation übergeben, wenn die Animation Ihrer didStopSelector Funktion stoppt entscheiden kann, ob es etwas tun soll oder nur zurück, basierend auf dem aktuellen Stand und den Zustandswert als Kontext übergeben.

Swift-Version von Stephen Darlington-Lösung

UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(0.1)
// other animation properties

// set view properties
UIView.commitAnimations()
CALayer * pLayer = self.layer.presentationLayer;
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView animateWithDuration:0.001 animations:^{
    self.frame = pLayer.frame;
}];

eine Animation pausieren, ohne Zustand Original zurückkehrt oder endgültig:

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

Wenn ich mit UIStackView Animation arbeiten, neben removeAllAnimations() Ich brauche ein paar Werte setzen eine Erstausbildung, weil removeAllAnimations() sie unberechenbar Zustand einstellen. Ich habe stackView mit view1 und view2 nach innen, und ein Blick sichtbar sein und eine versteckt:

public func configureStackView(hideView1: Bool, hideView2: Bool) {
    let oldHideView1 = view1.isHidden
    let oldHideView2 = view2.isHidden
    view1.layer.removeAllAnimations()
    view2.layer.removeAllAnimations()
    view.layer.removeAllAnimations()
    stackView.layer.removeAllAnimations()
    // after stopping animation the values are unpredictable, so set values to old
    view1.isHidden = oldHideView1 //    <- Solution is here
    view2.isHidden = oldHideView2 //    <- Solution is here

    UIView.animate(withDuration: 0.3,
                   delay: 0.0,
                   usingSpringWithDamping: 0.9,
                   initialSpringVelocity: 1,
                   options: [],
                   animations: {
                    view1.isHidden = hideView1
                    view2.isHidden = hideView2
                    stackView.layoutIfNeeded()
    },
                   completion: nil)
}

Keiner der beantworteten Lösungen für mich gearbeitet. Ich löste auf diese Weise meiner Probleme (ich weiß nicht, ob es ein richtiger Weg ist?), Weil ich Probleme hatte, als dies zu schnelle Aufruf (wenn vorherige Animation noch nicht fertig war). Ich gebe meine gewünschte Animation mit customAnim Block.

extension UIView
{

    func niceCustomTranstion(
        duration: CGFloat = 0.3,
        options: UIView.AnimationOptions = .transitionCrossDissolve,
        customAnim: @escaping () -> Void
        )
    {
        UIView.transition(
            with: self,
            duration: TimeInterval(duration),
            options: options,
            animations: {
                customAnim()
        },
            completion: { (finished) in
                if !finished
                {
                    // NOTE: This fixes possible flickering ON FAST TAPPINGS
                    // NOTE: This fixes possible flickering ON FAST TAPPINGS
                    // NOTE: This fixes possible flickering ON FAST TAPPINGS
                    self.layer.removeAllAnimations()
                    customAnim()
                }
        })

    }

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top