Anulează o animație UIView?

voturi
221

Este posibil pentru a anula o UIViewanimație în timp ce este în curs de desfășurare? Sau mi - ar trebui să scadă la nivelul CA?

adică am făcut ceva de genul asta (poate stabilirea unei acțiuni de animație final prea):

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

// set view properties

[UIView commitAnimations];

Dar, înainte de animație completează și am obține evenimentul de animație încheiat, vreau să-l anulați (se taie scurt). Este posibil? Googling în jurul găsește câțiva oameni care solicită aceeași întrebare cu răspunsuri - și unul sau doi oameni speculează că nu se poate face.

Întrebat 17/02/2009 la 00:19
sursa de către utilizator
În alte limbi...                            


17 răspunsuri

voturi
342

Utilizare:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];
Publicat 19/03/2010 la 07:53
sursa de către utilizator

voturi
111

Modul în care am face acest lucru este de a crea o nouă animație la punctul final. Setați o durată foarte scurtă și asigurați - vă că utilizați +setAnimationBeginsFromCurrentState:metoda pentru a porni de la starea actuală. Când ați setat la YES, animația curentă este tăiat scurt. Se pare ceva de genul:

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

// set view properties

[UIView commitAnimations];
Publicat 08/05/2009 la 22:46
sursa de către utilizator

voturi
61

Mai simplu mod de a opri toate animațiile pe un anumit punct de vedere, imediat , este aceasta:

Link proiectul la QuartzCore.framework. La începutul codului:

#import <QuartzCore/QuartzCore.h>

Acum, când doriți să opriți toate animațiile de pe un mort vedere în piesele lor, spun acest lucru:

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

Linia de mijloc ar funcționa de la sine, dar există o întârziere până când se termină runloop (la „redesenarea moment“). Pentru a evita această întârziere, înfășurați comanda într-un bloc de tranzacție explicită așa cum este prezentat. Aceste lucrări nu prevede alte modificări au fost efectuate pe acest strat în runloop curent.

Publicat 04/01/2012 la 00:03
sursa de către utilizator

voturi
43

Pe iOS 4 și mai mare, utilizați UIViewAnimationOptionBeginFromCurrentStateopțiunea a doua animație pentru a reduce prima animație de scurt.

Ca un exemplu, să presupunem că aveți o vedere cu un indicator de activitate. Dorești să se estompeze în timp ce indicatorul de activitate începe o anumită potențial activitate consumatoare de timp, și se estompeze - l atunci când activitatea este terminat. În codul de mai jos, ecranul cu indicatorul de activitate pe ea se numește 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;
                     }
                 }];
}
Publicat 11/08/2011 la 09:30
sursa de către utilizator

voturi
39

Pentru a anula o animație trebuie doar să setați proprietatea pe care este în prezent în curs animat, in afara de animație UIView. Acest lucru se va opri animația ori de câte ori este, iar UIView va sari la setarea pe care tocmai ați definit.

Publicat 19/06/2010 la 18:09
sursa de către utilizator

voturi
9

Dacă sunteți animarea o constrângere prin schimbarea constantă în loc de o vedere niciuna proprietate a alte metode de lucru pe iOS 8.

Exemplu de animație:

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

                 }];

Soluţie:

Ai nevoie pentru a elimina animatiile din straturile de orice opinii fiind afectate de schimbarea de constrângere și substraturile lor.

[self.constraintView.layer removeAllAnimations];
for (CALayer *l in self.constraintView.layer.sublayers)
{
    [l removeAllAnimations];
}
Publicat 07/11/2014 la 17:21
sursa de către utilizator

voturi
8

Imi pare rau sa reinvie acest răspuns, dar în iOS 10 lucruri schimbat cam, iar acum este posibilă anularea și puteți chiar anula cu grație!

După iOS 10 puteți anula animații cu UIViewPropertyAnimator !

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

Dacă treci adevărat anulează animația și oprește chiar în cazul în care l-ați anulat. Metoda de finalizare nu va fi numit. Cu toate acestea, dacă treci fals sunteți responsabil pentru finisare animație:

animator.finishAnimation(.start)

Puteți termina animația și să rămână în starea actuală (.current) sau du-te la starea inițială (.start) sau la starea de capăt (.end)

Apropo, puteți întrerupe și relua mai târziu, chiar ...

animator.pauseAnimation()
animator.startAnimation()

Notă: Dacă nu doriți o bruscă de anulare puteți inversa animația sau chiar schimba animație după ce o pauză!

Publicat 09/11/2017 la 17:57
sursa de către utilizator

voturi
7

Dacă doriți doar pentru a întrerupe / opri animație lin

self.yourView.layer.speed = 0;

Sursa: Cum de a întrerupe animația unui copac strat

Publicat 29/06/2015 la 11:02
sursa de către utilizator

voturi
5
[UIView setAnimationsEnabled:NO];
// your code here
[UIView setAnimationsEnabled:YES];
Publicat 06/02/2015 la 05:30
sursa de către utilizator

voturi
5

Nici una din cele de mai sus rezolvat pentru mine, dar acest lucru a ajutat: a UIViewanimației setează imediat proprietatea, apoi animă. Se oprește animația atunci când stratul de prezentare corespunde modelului (proprietatea set).

Am rezolvat problema mea, care a fost „Vreau să animați de unde ai arata ca tine apar“ ( „tu“ ceea ce înseamnă punctul de vedere). Dacă doriți ca, atunci:

  1. Adăugați QuartzCore.
  2. CALayer * pLayer = theView.layer.presentationLayer;

setați poziția la stratul de prezentare

Eu folosesc câteva opțiuni, inclusiv UIViewAnimationOptionOverrideInheritedDuration

Dar, pentru că documentația Apple este vagă, nu știu dacă este într-adevăr suprascrie alte animații atunci când sunt utilizate, sau doar resetează cronometre.

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

Și că ar trebui să fie o soluție decentă pentru acum.

Publicat 16/08/2011 la 18:21
sursa de către utilizator

voturi
1

Am aceeasi problema; API-urile nu au nimic de a anula unele animație specifice.

+ (void)setAnimationsEnabled:(BOOL)enabled

dezactivează toate animații, și, astfel, nu funcționează pentru mine. Există două soluții:

1) face animat dvs. obiecta un subview. Apoi, atunci când doriți să anulați animații pentru vizualizare, îndepărtați ecranul sau ascunde. Foarte simplu, dar ai nevoie pentru a recrea subview fără animații, dacă aveți nevoie să-l păstrați în vedere.

2) se repetă Anim doar unul, și să facă un selector delegat pentru a reporni Anim, dacă este necesar, ca aceasta:

-(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 cu 2) este că există întotdeauna întârzie oprirea Anim cum se termină ciclul de animație curent.

Sper că acest lucru vă ajută.

Publicat 08/05/2009 la 18:03
sursa de către utilizator

voturi
0

Nici una dintre soluțiile de răspuns a lucrat pentru mine. Am rezolvat problemele mele acest fel (nu știu dacă este un mod corect?), Pentru că am avut probleme atunci când acest apel prea repede (când animația anterioară nu a fost încă terminat). Am trece de animație mea a vrut cu customAnim bloc.

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

    }

}
Publicat 20/08/2019 la 14:52
sursa de către utilizator

voturi
0

Când lucrez cu UIStackViewanimație, pe langa removeAllAnimations()am nevoie pentru a seta anumite valori inițiale unul , deoarece removeAllAnimations()ele pot seta la starea imprevizibile. Am stackViewcu view1și în view2interior, și o vedere ar trebui să fie vizibile și unul ascuns:

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)
}
Publicat 07/02/2019 la 09:03
sursa de către utilizator

voturi
0

Versiunea Swift a soluției Stephen Darlington

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

// set view properties
UIView.commitAnimations()
Publicat 26/12/2017 la 15:09
sursa de către utilizator

voturi
0

Pentru a întrerupe o animație, fără revenirea la starea inițială sau finală:

CFTimeInterval paused_time = [myView.layer convertTime:CACurrentMediaTime() fromLayer:nil];
myView.layer.speed = 0.0;
myView.layer.timeOffset = paused_time;
Publicat 03/12/2015 la 21:43
sursa de către utilizator

voturi
0
CALayer * pLayer = self.layer.presentationLayer;
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView animateWithDuration:0.001 animations:^{
    self.frame = pLayer.frame;
}];
Publicat 28/01/2013 la 15:54
sursa de către utilizator

voturi
0

Chiar dacă anulați animația în modurile de mai sus de animație didStopSelectorîncă rulează. Deci , dacă aveți stări logice în aplicația conduse de animații vei avea probleme. Din acest motiv , cu modalitățile descrise mai sus folosesc variabila contextul UIViewanimații. Dacă treci starea actuală a programului de param context animație, atunci când animația se oprește dvs. didStopSelectorfuncția poate decide dacă ar trebui să facă ceva sau să se întoarcă în funcție de starea actuală și valoarea de stat a trecut ca și context.

Publicat 05/10/2010 la 09:52
sursa de către utilizator

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