Domanda

E 'possibile cancellare un'animazione UIView mentre è in corso? Oppure avrei dovuto scendere a livello di CA?

vale a dire. Ho fatto qualcosa di simile (forse impostando un'azione di animazione fine troppo):

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

// set view properties

[UIView commitAnimations];

Ma prima che l'animazione completa e ottengo l'animazione è conclusa manifestazione, voglio cancellarlo (tagliare corto). È possibile? Googling intorno trova poche persone che chiedono la stessa domanda senza risposte -. E una o due persone che speculano che non può essere fatto

È stato utile?

Soluzione

Il modo in cui lo faccio è quello di creare una nuova animazione al punto finale. Impostare una durata molto breve e assicurarsi che si utilizza il metodo +setAnimationBeginsFromCurrentState: per iniziare dallo stato attuale. Quando si imposta su SI, l'animazione corrente viene tagliato corto. Sembra qualcosa di simile:

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

// set view properties

[UIView commitAnimations];

Altri suggerimenti

Usa:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];

modo più semplice per fermare tutti animazioni in una vista particolare, immediatamente , è questo:

collegare il progetto ad QuartzCore.framework. All'inizio del codice:

#import <QuartzCore/QuartzCore.h>

Ora, quando si desidera interrompere tutte le animazioni in un vicolo vista nella loro tracce, dire questo:

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

La linea mediana dovrebbe funzionare da sola, ma c'è un ritardo fino al termine runloop (il "ridisegnare momento"). Per evitare questo ritardo, avvolgere il comando in un blocco di transazione esplicita, come mostrato. Questo funziona previsti altri cambiamenti sono stati effettuati su questo livello nel runloop corrente.

Su iOS 4 e maggiore, utilizzare l'opzione UIViewAnimationOptionBeginFromCurrentState sulla seconda animazione di tagliare la prima animazione breve.

Per fare un esempio, si supponga di avere una vista con un indicatore di attività. Si vuole svanire nel indicatore di attività, mentre alcuni potenzialmente tempo attività inizia, e dissolvenza fuori quando l'attività è terminata. Nel seguente codice, la vista con l'indicatore di attività si chiama il 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;
                     }
                 }];
}

Per annullare un'animazione è sufficiente impostare la proprietà che è attualmente in corso di animazione, al di fuori dell'animazione UIView. Che fermerà l'animazione dovunque sia, e l'UIView salterà l'impostazione appena definita.

Siamo spiacenti di far risorgere questa risposta, ma in iOS 10 cose po 'cambiato, e ora l'annullamento è possibile e si può anche cancellare la grazia!

Dopo iOS 10 è possibile annullare le animazioni con UIViewPropertyAnimator !

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

Se si passa vero annulla l'animazione e si ferma proprio dove è stata annullata esso. Il metodo di completamento non sarà chiamato. Tuttavia, se si passa falso di essere responsabile per la finitura l'animazione:

animator.finishAnimation(.start)

Si può terminare l'animazione e rimanere allo stato attuale (.Current) o andare allo stato iniziale (.start) o lo stato finale (.end)

A proposito, si può anche mettere in pausa e riavviare dopo ...

animator.pauseAnimation()
animator.startAnimation()

Nota: Se non si desidera un brusco annullamento si può invertire l'animazione o anche cambiare l'animazione dopo aver sospeso lo

Se si sta animando un vincolo cambiando la costante invece di una finestra delle proprietà nessuno degli altri metodi di lavorare su iOS 8.

Esempio di animazione:

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) {

                 }];

Soluzione:

È necessario rimuovere le animazioni dagli strati di eventuali pareri di essere interessata dalla modifica vincolo e le loro sottolivelli.

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

Se si vuole solo mettere in pausa / stop di animazione senza intoppi

self.yourView.layer.speed = 0;

Fonte: Come mettere in pausa l'animazione di un albero strato di

Nessuno dei precedenti risolto per me, ma questo ha aiutato: L'animazione UIView imposta immediatamente la proprietà, poi lo anima. Si ferma l'animazione quando il livello di presentazione corrisponde al modello (la proprietà impostata).

Ho risolto il mio problema, che è stato "Voglio animare da dove si guarda come appari" ( 'si' che significa la vista). Se si desidera che questo, allora:

  1. Aggiungi QuartzCore.
  2. CALayer * pLayer = theView.layer.presentationLayer;

impostare la posizione al livello di presentazione

Io uso un paio di opzioni, tra cui UIViewAnimationOptionOverrideInheritedDuration

Ma poiché la documentazione di Apple è vaga, non so se prevale davvero le altre animazioni quando viene utilizzato, o semplicemente azzera 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) {}];

E che dovrebbe essere una soluzione decente per ora.

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

Ho lo stesso problema; le API non hanno nulla di annullare qualche animazione specifica. Il

+ (void)setAnimationsEnabled:(BOOL)enabled

disabilita tutte le animazioni, e quindi non funziona per me. Ci sono due soluzioni:

1) rendere il vostro oggetto animato una visualizzazione secondaria. Poi, quando si desidera annullare le animazioni per quella vista, rimuovere la vista o nasconderlo. Molto semplice, ma è necessario ricreare la visualizzazione secondaria senza animazioni se è necessario tenerlo in considerazione.

2) ripetere l'anim sola, e fare un selettore delegato per riavviare l'Anim, se necessario, in questo modo:

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

Problema con 2) è che c'è sempre ritardare l'arresto del anim come termina il ciclo di animazione corrente.

Spero che questo aiuti.

Anche se si annulla l'animazione nei modi di cui sopra animazione didStopSelector corre ancora. Quindi, se avete stati logici nell'applicazione guidato da animazioni si avranno problemi. Per questo motivo, con le modalità sopra descritte utilizzare la variabile di contesto di animazioni UIView. Se si passa lo stato attuale del vostro programma dal contesto param per l'animazione, quando l'animazione si ferma la funzione didStopSelector può decidere se si dovrebbe fare qualcosa o semplicemente tornare sulla base dello stato attuale e il valore dello stato passato come contesto.

Versione Swift della soluzione di Stephen Darlington

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

Per mettere in pausa un'animazione senza ritornare stato di originale o finale:

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

Quando lavoro con l'animazione UIStackView, oltre removeAllAnimations() ho bisogno di impostare alcuni valori di siglare uno perché removeAllAnimations() li può impostare a stato imprevedibile. Ho stackView con view1 e view2 dentro, e un punto di vista deve essere visibile e uno nascosto:

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)
}

Nessuna delle soluzioni risposto lavorato per me. Ho risolto i miei problemi in questo modo (non so se è un modo corretto?), Perché ho avuto problemi quando si chiama questo troppo veloce (quando l'animazione precedente non era ancora finito). Io passo la mia animazione desiderato con customAnim di blocco.

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()
                }
        })

    }

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top