Annuleer een UIView animatie?

stemmen
221

Is het mogelijk om een annuleren UIViewanimatie terwijl deze aan de gang is? Of zou ik moeten dalen tot de CA-niveau?

dwz Ik heb zoiets als dit (misschien het instellen van een einde animatieactie ook) gedaan:

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

// set view properties

[UIView commitAnimations];

Maar voordat de animatie is voltooid en ik krijg de animatie eindigde evenement, ik wil het annuleren (snijd het kort). Is dit mogelijk? Googlen rond vindt een paar mensen dezelfde vraag stellen met geen antwoorden - en één of twee mensen speculeren dat het niet kan worden gedaan.

De vraag is gesteld op 17/02/2009 om 00:19
bron van user
In andere talen...                            


17 antwoorden

stemmen
342

Gebruik:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];
antwoordde op 19/03/2010 om 07:53
bron van user

stemmen
111

De manier waarop ik het doen is om een nieuwe animatie om uw eindpunt te creëren. Stel een zeer korte duur en zorg ervoor dat u het gebruiken +setAnimationBeginsFromCurrentState:methode uit te gaan van de huidige toestand. Wanneer je het op JA, wordt de huidige animatie ingekort. Ziet er ongeveer als volgt uit:

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

// set view properties

[UIView commitAnimations];
antwoordde op 08/05/2009 om 22:46
bron van user

stemmen
61

Eenvoudigste manier om te stoppen met alle animaties op een bepaalde visie, onmiddellijk , is dit:

Koppel het project QuartzCore.framework. Aan het begin van de code:

#import <QuartzCore/QuartzCore.h>

Nu, als u alle animaties op het oog dood te stoppen in hun sporen, dit zeggen:

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

De middelste lijn zou werken op zichzelf, maar er is een vertraging totdat de runLoop afwerkingen (het "opnieuw tekenen moment"). Om deze vertraging te voorkomen, wikkel het commando in een expliciete transactie blok zoals afgebeeld. Deze werken mits er geen andere veranderingen werden uitgevoerd op deze laag in de huidige runLoop.

antwoordde op 04/01/2012 om 00:03
bron van user

stemmen
43

Op iOS 4 en hoger, gebruik maken van de UIViewAnimationOptionBeginFromCurrentStateoptie op de tweede animatie om de eerste animatie ingekort.

Als voorbeeld, neem aan dat je een uitzicht met een activiteit indicator. U wenst te vervagen in de indicator, terwijl een aantal potentieel tijdrovende bezigheid begint, en fade het uit wanneer de activiteit is voltooid. In de onderstaande code, wordt de weergave met de indicator op genoemd 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;
                     }
                 }];
}
antwoordde op 11/08/2011 om 09:30
bron van user

stemmen
39

Als u een animatie je gewoon nodig om de woning die momenteel wordt geanimeerd, buiten de UIView animatie set te annuleren. Dat zal de animatie te stoppen waar het ook is, en de UIView zal gaan naar de instelling die u zojuist gedefinieerd.

antwoordde op 19/06/2010 om 18:09
bron van user

stemmen
9

Als u animeren een beperking door de constante veranderen in plaats van het oog eigenschap geen van de andere methoden werken op iOS-8.

Bijvoorbeeld animatie:

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

                 }];

Oplossing:

U moet de animaties van de lagen van de standpunten te verwijderen wordt beïnvloed door de beperking verandering en hun sublagen.

[self.constraintView.layer removeAllAnimations];
for (CALayer *l in self.constraintView.layer.sublayers)
{
    [l removeAllAnimations];
}
antwoordde op 07/11/2014 om 17:21
bron van user

stemmen
8

Sorry dat ik dit antwoord leven in te blazen, maar in iOS 10 dingen een beetje veranderd, en nu annuleren is mogelijk en je kunt zelfs sierlijk annuleren!

Na iOS 10 kun je animaties annuleren UIViewPropertyAnimator !

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

Als je trouw doorgeven annuleert de animatie en het stopt daar waar je deze geannuleerd. De voltooiing werkwijze wordt niet genoemd. Echter, als je vals voorbij bent u verantwoordelijk voor het afwerken van de animatie:

animator.finishAnimation(.start)

U kunt uw animatie af te maken en te blijven in de huidige staat (.current) of ga naar de oorspronkelijke staat (.start) of naar de eindtoestand (.end)

By the way, kunt u zelfs pauzeren en later opnieuw op te starten ...

animator.pauseAnimation()
animator.startAnimation()

Opmerking: Als u niet wilt dat een abrupt annuleren kunt u uw animatie ongedaan te maken of zelfs te veranderen je animatie nadat u het pauzeren!

antwoordde op 09/11/2017 om 17:57
bron van user

stemmen
7

Als je gewoon wilt onderbreken / stoppen animatie soepel

self.yourView.layer.speed = 0;

Bron: Hoe de animatie van een laag boom pauzeren

antwoordde op 29/06/2015 om 11:02
bron van user

stemmen
5
[UIView setAnimationsEnabled:NO];
// your code here
[UIView setAnimationsEnabled:YES];
antwoordde op 06/02/2015 om 05:30
bron van user

stemmen
5

Geen van de bovenstaande opgelost voor mij, maar dit hielp: De UIViewanimatie stelt de eigenschap onmiddellijk, dan bezielt. Het stopt de animatie als de presentatielaag overeenkomt met het model (de set eigendom).

Ik loste mijn probleem, dat was "Ik wil animeren van waar je ziet eruit alsof je in de realiteit" ( 'jij' wat betekent dat de weergave). Als u dat wilt, dan:

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

om de positie op de presentatielaag

Ik gebruik een paar opties, waaronder UIViewAnimationOptionOverrideInheritedDuration

Maar omdat Apple's documentatie is vaag, ik weet niet of het echt heeft voorrang op de andere animaties wanneer het wordt gebruikt, of gewoon reset timers.

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

En dat zou een fatsoenlijke oplossing voor nu.

antwoordde op 16/08/2011 om 18:21
bron van user

stemmen
1

Ik heb hetzelfde probleem; de API's niet iets om een ​​aantal specifieke animatie te annuleren. De

+ (void)setAnimationsEnabled:(BOOL)enabled

schakelt alle animaties, en dus werkt niet voor mij. Er zijn twee oplossingen:

1) maak uw geanimeerde een subview bezwaar te maken. Dan, wanneer u de animaties te annuleren voor die opvatting, verwijder het uitzicht of te verbergen. Heel simpel, maar je moet de subview opnieuw zonder animatie als je nodig hebt om het in beeld te houden.

2) herhaal de Anim slechts één, en maak een afgevaardigde selector om de anim opnieuw op te starten als dat nodig is, als volgt uit:

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

Probleem met 2) is dat er altijd vertraging stoppen van de anim als het klaar is de huidige animatie cyclus.

Ik hoop dat dit helpt.

antwoordde op 08/05/2009 om 18:03
bron van user

stemmen
0

Geen van de beantwoorde oplossingen gewerkt voor mij. Ik loste mijn problemen op deze manier (ik weet niet of het een correcte manier?), Want ik had problemen bij het aanroepen van dit te-snel (als vorige animatie was nog niet voltooid). Ik pas mijn gewenste animatie met customAnim blok.

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

    }

}
antwoordde op 20/08/2019 om 14:52
bron van user

stemmen
0

Wanneer ik werk met UIStackViewanimatie, naast removeAllAnimations()Ik moet sommige waarden ingesteld op een initiële omdat removeAllAnimations()hen kan ingesteld op onvoorspelbare toestand achter. Ik heb stackViewmet view1en view2binnen en één weergave moeten zichtbaar zijn en een verborgen:

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)
}
antwoordde op 07/02/2019 om 09:03
bron van user

stemmen
0

Swift versie van de oplossing Stephen Darlington

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

// set view properties
UIView.commitAnimations()
antwoordde op 26/12/2017 om 15:09
bron van user

stemmen
0

Als u een animatie te onderbreken zonder het terugkeren staat de oorspronkelijke of definitieve:

CFTimeInterval paused_time = [myView.layer convertTime:CACurrentMediaTime() fromLayer:nil];
myView.layer.speed = 0.0;
myView.layer.timeOffset = paused_time;
antwoordde op 03/12/2015 om 21:43
bron van user

stemmen
0
CALayer * pLayer = self.layer.presentationLayer;
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView animateWithDuration:0.001 animations:^{
    self.frame = pLayer.frame;
}];
antwoordde op 28/01/2013 om 15:54
bron van user

stemmen
0

Zelfs als je de animatie in de wegen bovenstaande animatie annuleren didStopSelectorloopt nog. Dus als je logische toestanden in uw toepassing gedreven door animaties zul je problemen hebben. Daarom de bovenbeschreven ik contextvariabele gebruik van manieren UIViewanimaties. Als u de huidige staat van het programma langs de context param om de animatie, wanneer de animatie stopt uw didStopSelectorfunctie kan beslissen of het iets moet doen of gewoon terug te keren op basis van de huidige toestand en de staat waarde doorgegeven als context.

antwoordde op 05/10/2010 om 09:52
bron van user

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