¿Cancelar una animación UIView?

votos
221

¿Es posible cancelar una UIViewanimación mientras está en progreso? ¿O tendría que bajar al nivel CA?

es decir, he hecho algo como esto (tal vez establecer una acción de animación final también):

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

// set view properties

[UIView commitAnimations];

Pero antes de que la animación se complete y recibo el evento de animación finalizada, quiero cancelarlo (abreviarlo). es posible? Buscar en Google encuentra a algunas personas que hacen la misma pregunta sin respuestas, y una o dos personas especulan que no se puede hacer.

Publicado el 17/02/2009 a las 00:19
fuente por usuario
En otros idiomas...                            


17 respuestas

votos
342

Utilizar:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];
Respondida el 19/03/2010 a las 07:53
fuente por usuario

votos
111

La forma en que lo hago es crear una nueva animación para su punto final. Establezca una duración muy corta y asegúrese de usar el +setAnimationBeginsFromCurrentState:método para comenzar desde el estado actual. Cuando lo configura en SÍ, la animación actual se acorta. Se ve algo como esto:

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

// set view properties

[UIView commitAnimations];
Respondida el 08/05/2009 a las 22:46
fuente por usuario

votos
61

Forma más sencilla para detener todas las animaciones en una visión particular, de inmediato , es la siguiente:

Vincular el proyecto a QuartzCore.framework. Al comienzo de su código:

#import <QuartzCore/QuartzCore.h>

Ahora, cuando se desea detener todas las animaciones en una vista de muertos en sus pistas, decir lo siguiente:

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

La línea media podría funcionar por sí mismo, pero hay un retraso hasta que termine el Runloop (el "redibujar momento"). Para evitar este retraso, envuelva el comando en un bloque de transacción explícita como se muestra. Estos trabajos previstos otros cambios se han realizado en esta capa en el runloop actual.

Respondida el 04/01/2012 a las 00:03
fuente por usuario

votos
43

En iOS 4 y mayor, utilice la UIViewAnimationOptionBeginFromCurrentStateopción de la segunda animación para cortar el primer corto de animación.

A modo de ejemplo, supongamos que tiene una vista con un indicador de actividad. Quiera realizar el fundido en el indicador de actividad, mientras que algunos pueden llevar un tiempo que consume la actividad comienza, y se desvanecen a cabo una vez finalizada la actividad. En el siguiente código, la vista con el indicador de la actividad en que se llama 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;
                     }
                 }];
}
Respondida el 11/08/2011 a las 09:30
fuente por usuario

votos
39

Para cancelar una animación sólo hay que establecer la propiedad que está siendo animado, fuera de la animación UIView. Que detenga la animación dondequiera que sea, y la UIView saltará a la configuración que acaba de definir.

Respondida el 19/06/2010 a las 18:09
fuente por usuario

votos
9

Si está animando una restricción cambiando la constante en lugar de una vista ninguna propiedad de los otros métodos de trabajar en iOS 8.

animación Ejemplo:

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

                 }];

Solución:

Es necesario eliminar las animaciones de las capas de los puntos de vista de ser afectado por el cambio y la restricción de sus subcapas.

[self.constraintView.layer removeAllAnimations];
for (CALayer *l in self.constraintView.layer.sublayers)
{
    [l removeAllAnimations];
}
Respondida el 07/11/2014 a las 17:21
fuente por usuario

votos
8

Lo sentimos para resucitar esta respuesta, pero en iOS 10 cosas cambiaron un poco, y ahora la cancelación es posible e incluso se puede cancelar con gracia!

Después de 10 IOS puede cancelar animaciones con UIViewPropertyAnimator !

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

Si pasa cierto que cancela la animación y se detiene justo donde se canceló. El método de ejecución no será llamado. Sin embargo, si pasa falsa usted es responsable de terminar la animación:

animator.finishAnimation(.start)

Puede terminar su animación y permanecer en el estado actual (.Current) o ir al estado inicial (.start) o al estado final (.end)

Por cierto, incluso se puede hacer una pausa y reiniciar más tarde ...

animator.pauseAnimation()
animator.startAnimation()

Nota: Si no desea que una abrupta cancelación se puede revertir la animación o incluso cambiar la animación después de interrumpir la pena!

Respondida el 09/11/2017 a las 14:57
fuente por usuario

votos
7

Si lo que desea es hacer una pausa / parada de la animación sin problemas

self.yourView.layer.speed = 0;

Fuente: Cómo detener la animación de un árbol de capas

Respondida el 29/06/2015 a las 11:02
fuente por usuario

votos
5
[UIView setAnimationsEnabled:NO];
// your code here
[UIView setAnimationsEnabled:YES];
Respondida el 06/02/2015 a las 05:30
fuente por usuario

votos
5

Ninguna de las anteriores resuelve para mí, pero esto ayudó: La UIViewanimación se establece la propiedad de inmediato, entonces la anima. Se detiene la animación cuando la capa de presentación coincida con el modelo (el conjunto de propiedades).

He resuelto mi problema, que estaba "Quiero animar desde donde se mira como usted aparece" ( 'usted' significa la vista). Si quieres eso, entonces:

  1. Añadir QuartzCore.
  2. CALayer * pLayer = theView.layer.presentationLayer;

establecer la posición de la capa de presentación

Yo uso un par de opciones, entre ellas UIViewAnimationOptionOverrideInheritedDuration

Pero debido a que la documentación de Apple es vaga, no sé si realmente prevalece sobre las otras animaciones cuando se utiliza, o simplemente restablece los temporizadores.

[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) {}];

Y eso debería ser una solución decente por ahora.

Respondida el 16/08/2011 a las 18:21
fuente por usuario

votos
1

Tengo el mismo problema; las API no tienen nada para cancelar algunas animaciones específicas. los

+ (void)setAnimationsEnabled:(BOOL)enabled

deshabilita TODAS las animaciones, y por lo tanto no funciona para mí. Hay dos soluciones:

1) haz que tu objeto animado sea una subvista. Luego, cuando desee cancelar las animaciones para esa vista, elimine la vista u ocúltela. Muy simple, pero necesita recrear la subvista sin animaciones si necesita mantenerla a la vista.

2) repite solo el anim y crea un selector de delegados para reiniciar el anim si es necesario, como este:

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

El problema con 2) es que siempre hay demora para detener el anim mientras termina el ciclo de animación actual.

Espero que esto ayude.

Respondida el 08/05/2009 a las 18:03
fuente por usuario

votos
0

Ninguna de las soluciones contestadas trabajó para mí. Me resuelto mis problemas de esta manera (no sé si se trata de una manera correcta?), Porque tenía problemas al llamar a esta demasiado rápido (cuando la animación anterior aún no había terminado). Paso mi animación deseada con customAnim bloque.

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

    }

}
Respondida el 20/08/2019 a las 14:52
fuente por usuario

votos
0

Cuando trabajo con UIStackViewla animación, además removeAllAnimations()tengo que configurar algunos valores iniciales a uno porque removeAllAnimations()se los puso a estado impredecible. Tengo stackViewcon view1y view2en el interior, y una vista debería ser visible y uno oculto:

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)
}
Respondida el 07/02/2019 a las 09:03
fuente por usuario

votos
0

SWIFT versión de la solución de Stephen Darlington

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

// set view properties
UIView.commitAnimations()
Respondida el 26/12/2017 a las 12:09
fuente por usuario

votos
0

Para detener una animación sin volver a estado original o final:

CFTimeInterval paused_time = [myView.layer convertTime:CACurrentMediaTime() fromLayer:nil];
myView.layer.speed = 0.0;
myView.layer.timeOffset = paused_time;
Respondida el 03/12/2015 a las 18:43
fuente por usuario

votos
0
CALayer * pLayer = self.layer.presentationLayer;
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView animateWithDuration:0.001 animations:^{
    self.frame = pLayer.frame;
}];
Respondida el 28/01/2013 a las 15:54
fuente por usuario

votos
0

Aunque cancele la animación en las formas anteriores de animación didStopSelectortodavía funciona. Así que si usted tiene estados lógicos en su aplicación impulsada por animaciones tendrá problemas. Por esta razón, con las formas descritas anteriormente utilizo la variable contexto de UIViewanimaciones. Si pasa el estado actual de su programa por el contexto parámetro a la animación, cuando la animación se detiene su didStopSelectorfunción puede decidir si se debe hacer algo o simplemente volver basado en el estado actual y el valor de estado pasa como contexto.

Respondida el 05/10/2010 a las 09:52
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more