Avbryte en UIView animasjon?

stemmer
225

Er det mulig å avbryte en UIViewanimasjon mens det pågår? Eller ville jeg slippe til CA nivå?

dvs. jeg har gjort noe som dette (kanskje sette en stopper animasjonen handling også):

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

// set view properties

[UIView commitAnimations];

Men før animasjonen er ferdig og jeg får animasjonen endte hendelse, jeg ønsker å avbryte den (klippe det kort). Er dette mulig? Googling rundt finner noen folk som spør det samme spørsmålet uten svar - og en eller to personer spekulerer at det ikke kan gjøres.

Publisert på 16/02/2009 klokken 23:19
kilden bruker
På andre språk...                            


17 svar

stemmer
345

Bruk:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];
Svarte 19/03/2010 kl. 06:53
kilden bruker

stemmer
111

Måten jeg gjør det er å lage en ny animasjon til sluttpunktet. Sett en svært kort varighet, og sørg for at du bruker +setAnimationBeginsFromCurrentState:metoden for å starte fra den nåværende tilstand. Når du setter den til JA, er den nåværende animasjonen klippe kort. Ser omtrent slik ut:

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

// set view properties

[UIView commitAnimations];
Svarte 08/05/2009 kl. 21:46
kilden bruker

stemmer
62

Enkleste måten å stoppe alle animasjoner på en bestemt visning, umiddelbart , er dette:

Knytte prosjektet til QuartzCore.framework. Ved starten av koden:

#import <QuartzCore/QuartzCore.h>

Nå, når du ønsker å stoppe alle animasjoner på en visning døde i sitt spor, sier dette:

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

Den midterste linjen ville fungere helt av seg selv, men det er en forsinkelse før runloop ferdig (det "tegne moment"). For å hindre at forsinkelsen, vikle kommandoen i en eksplisitt transaksjon blokk som vist. Dette fungerer forutsatt ingen andre endringer har blitt utført på dette laget i dagens runloop.

Svarte 03/01/2012 kl. 23:03
kilden bruker

stemmer
45

På iOS 4 og større, bruker du UIViewAnimationOptionBeginFromCurrentStatealternativet på den andre animasjonen til å kutte den første animasjons kort.

Som et eksempel, anta at du har en visning med en aktivitet indikator. Du ønsker å visne i aktivitetsindikatoren mens noen potensielt tidkrevende aktivitet begynner, og fade det ut når aktiviteten er avsluttet. I koden nedenfor, er opprisset med aktiviteten indikatoren på det som kalles 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;
                     }
                 }];
}
Svarte 11/08/2011 kl. 08:30
kilden bruker

stemmer
39

Hvis du vil avbryte en animasjon du bare trenger å sette eiendommen som er under animert, utenfor UIView animasjon. Som vil stoppe animasjonen uansett hvor den er, og UIView vil hoppe til den innstillingen du nettopp definerte.

Svarte 19/06/2010 kl. 17:09
kilden bruker

stemmer
10

Beklager å gjenopplive dette svaret, men i iOS 10 ting litt endret, og nå avlyser er mulig, og du kan til og med avbryte grasiøst!

Etter iOS 10 kan du avbryte animasjoner med UIViewPropertyAnimator !

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

Hvis du passerer sant det avbryter animasjon og den stopper akkurat der du avbrøt den. Ferdigstillelse metoden vil ikke bli kalt. Men hvis du passerer falsk du er ansvarlig for etterbehandling animasjonen:

animator.finishAnimation(.start)

Du kan fullføre animasjonen og bo i nåværende tilstand (.current) eller gå til den opprinnelige tilstanden (.start) eller til slutten staten (END)

Forresten, kan du selv ta en pause og starte på nytt senere ...

animator.pauseAnimation()
animator.startAnimation()

Merk: Hvis du ikke vil at en brå avbryter du kan reversere animasjonen eller endre animasjonen etter at du har stoppet den!

Svarte 09/11/2017 kl. 17:57
kilden bruker

stemmer
9

Hvis du animere en begrensning ved å endre konstant i stedet for en eiendommen ingen av de andre metodene fungerer på iOS 8.

Eksempel animasjon:

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øsning:

Du må fjerne animasjoner fra lagene i noen visninger som blir berørt av begrensningen endring og deres sublayers.

[self.constraintView.layer removeAllAnimations];
for (CALayer *l in self.constraintView.layer.sublayers)
{
    [l removeAllAnimations];
}
Svarte 07/11/2014 kl. 17:21
kilden bruker

stemmer
7

Hvis du bare ønsker å pause / stopp animasjon jevnt

self.yourView.layer.speed = 0;

Kilde: Hvordan stanse animasjonen av et lag tre

Svarte 29/06/2015 kl. 11:02
kilden bruker

stemmer
5
[UIView setAnimationsEnabled:NO];
// your code here
[UIView setAnimationsEnabled:YES];
Svarte 06/02/2015 kl. 05:30
kilden bruker

stemmer
5

Ingen av de ovennevnte løste det for meg, men dette hjalp: Den UIViewanimasjonen setter eiendommen umiddelbart, deretter animeres det. Det stopper animasjonen når presentasjonen laget samsvarer med modellen (angitt egenskapen).

Jeg løste mitt problem, som var "Jeg ønsker å animere fra der du ser ut som du ser ut" ( 'du' betyr visning). Hvis du ønsker det, så:

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

angi posisjonen til presentasjonslaget

Jeg bruker et par alternativer inkludert UIViewAnimationOptionOverrideInheritedDuration

Men fordi Apples dokumentasjon er vage, jeg vet ikke om det virkelig overstyrer de andre animasjoner når de brukes, eller bare tilbake tidtakere.

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

Og det bør være en anstendig løsning for bedriften.

Svarte 16/08/2011 kl. 17:21
kilden bruker

stemmer
1

Jeg har samme problem; APIene har ikke noe å avbryte noen spesifikke animasjon. De

+ (void)setAnimationsEnabled:(BOOL)enabled

deaktiverer alle animasjoner, og dermed ikke fungerer for meg. Det finnes to løsninger:

1) gjøre animert objekt en subview. Deretter, når du vil avbryte animasjoner for denne visningen, fjerner utsikten eller skjule den. Veldig enkelt, men du trenger for å gjenskape subview uten animasjoner hvis du trenger å holde den i visningen.

2) gjenta anim eneste, og lage en delegat velgeren å starte anim om nødvendig, som dette:

-(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 med 2) er at det er alltid forsinke stoppe anim som den er ferdig gjeldende animasjon syklus.

Håper dette hjelper.

Svarte 08/05/2009 kl. 17:03
kilden bruker

stemmer
0

Ingen av de besvarte løsninger fungerte for meg. Jeg løste mine problemer på denne måten (jeg vet ikke om det er en riktig vei?), Fordi jeg hadde problemer når du ringer dette altfor fort (når forrige animasjon var ennå ikke ferdig). Jeg går min ville animasjon med customAnim blokk.

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

    }

}
Svarte 20/08/2019 kl. 14:52
kilden bruker

stemmer
0

Når jeg jobber med UIStackViewanimasjon, foruten removeAllAnimations()jeg må sette noen verdier førstegang en grunn removeAllAnimations()kan stille dem til uforutsigbar tilstand. Jeg har stackViewmed view1og view2inne, og en visning skal være synlig og ett skjult:

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)
}
Svarte 07/02/2019 kl. 09:03
kilden bruker

stemmer
0

Swift versjon av Stephen Darlington løsning

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

// set view properties
UIView.commitAnimations()
Svarte 26/12/2017 kl. 15:09
kilden bruker

stemmer
0

For å stoppe en animasjon uten å gå tilbake tilstand til opprinnelig eller endelig:

CFTimeInterval paused_time = [myView.layer convertTime:CACurrentMediaTime() fromLayer:nil];
myView.layer.speed = 0.0;
myView.layer.timeOffset = paused_time;
Svarte 03/12/2015 kl. 21:43
kilden bruker

stemmer
0
CALayer * pLayer = self.layer.presentationLayer;
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView animateWithDuration:0.001 animations:^{
    self.frame = pLayer.frame;
}];
Svarte 28/01/2013 kl. 14:54
kilden bruker

stemmer
0

Selv om du avbryter animasjonen på de måter ovenfor animasjon didStopSelectorfortsatt kjører. Så hvis du har logiske tilstander i din søknad drevet av animasjoner vil du ha problemer. Av denne grunn med måter som er beskrevet ovenfor jeg bruke kontekst variabel av UIViewanimasjoner. Hvis du passerer den nåværende tilstand av programmet av konteksten param til animasjon, når animasjonen stopper din didStopSelectorfunksjon kan bestemme om det skal gjøre noe eller bare gå tilbake basert på den nåværende tilstand og staten verdi sendt som kontekst.

Svarte 05/10/2010 kl. 08:52
kilden bruker

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