Anulować animacji UIView?

głosy
221

Czy to możliwe, aby anulować UIViewanimację podczas gdy ona jest w toku? Albo będę musiał spaść do poziomu CA?

tj Zrobiłem coś takiego (może ustawienie działania animacji końcowej zbyt):

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

// set view properties

[UIView commitAnimations];

Ale zanim zakończy się animacja i uzyskać zdarzenie animacji skończyło, chcę go odwołać (wyciąć go krótko). czy to możliwe? Googling wokół znajdzie kilka osób zadaje to samo pytanie bez odpowiedzi - oraz jeden lub dwóch ludzi spekulują, że nie można zrobić.

Utwórz 17/02/2009 o 00:19
źródło użytkownik
W innych językach...                            


17 odpowiedzi

głosy
342

Posługiwać się:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];
Odpowiedział 19/03/2010 o 07:53
źródło użytkownik

głosy
111

Sposób, w jaki to zrobić jest stworzenie nowej animacji do punktu końcowego. Ustawić bardzo krótki czas i upewnij się użyć +setAnimationBeginsFromCurrentState:metody zacząć od aktualnego stanu. Kiedy go ustawić na TAK, obecne ożywienie jest przerwana. Wygląda mniej więcej tak:

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

// set view properties

[UIView commitAnimations];
Odpowiedział 08/05/2009 o 22:46
źródło użytkownik

głosy
61

Najprostszym sposobem, aby zatrzymać wszystkie animacje na konkretnym zdaniem natychmiast , to:

Odwołuje się projekt do QuartzCore.framework. Na początku kodu:

#import <QuartzCore/QuartzCore.h>

Teraz, gdy chcemy, aby zatrzymać wszystkie animacje na widoku martwych w ich utworów, to powiedzieć:

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

Środkowa linia będzie działać sam z siebie, ale nie jest to opóźnienie, aż zakończy runloop (dalej „przerysować chwilę”). Aby uniknąć tego opóźnienia, owinąć polecenia w wyraźnej bloku transakcji, jak pokazano. Działa to przewidziane żadne inne zmiany zostały przeprowadzone na tej warstwy w bieżącym runloop.

Odpowiedział 04/01/2012 o 00:03
źródło użytkownik

głosy
43

IOS 4 i większej, należy wybrać UIViewAnimationOptionBeginFromCurrentStateopcję na drugim animacji do cięcia pierwszą animację krótki.

Jako przykład załóżmy, że masz widok ze wskaźnikiem aktywności. Chcesz znikać we wskaźniku aktywności, podczas gdy niektóre potencjalnie czasochłonne aktywność rozpoczyna się i zanikać ją, gdy działalność jest zakończona. W poniższym kodzie, widok ze wskaźnikiem aktywności na nim nazywa 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;
                     }
                 }];
}
Odpowiedział 11/08/2011 o 09:30
źródło użytkownik

głosy
39

Aby anulować animację wystarczy ustawić właściwość, która jest obecnie animowany, poza animacji UIView. Że będzie zatrzymać animację, gdziekolwiek to jest, a UIView przeskoczy do ustawienia po prostu zdefiniowane.

Odpowiedział 19/06/2010 o 18:09
źródło użytkownik

głosy
9

Jeśli animowanie ograniczenie poprzez zmianę stałej zamiast żaden widok własności innych metod pracy na iOS 8.

Przykład Animacja

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

                 }];

Rozwiązanie:

Trzeba usunąć animacje z warstwami jakichkolwiek poglądów są dotknięte przez zmiany więzów i ich podwarstwy.

[self.constraintView.layer removeAllAnimations];
for (CALayer *l in self.constraintView.layer.sublayers)
{
    [l removeAllAnimations];
}
Odpowiedział 07/11/2014 o 17:21
źródło użytkownik

głosy
8

Niestety wskrzesić tę odpowiedź, ale w iOS 10 rzeczy trochę zmieniły i teraz anulowanie jest możliwe i można nawet zrezygnować z wdziękiem!

Po iOS 10 można zrezygnować z animacji UIViewPropertyAnimator !

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

Jeśli przechodzą prawdziwe anuluje animację i zatrzymuje się dokładnie tam, gdzie go anulowane. Sposób zakończenia nie zostanie wywołana. Jeśli jednak przekazać fałszywe jesteś odpowiedzialny za animację wykończenia:

animator.finishAnimation(.start)

można zakończyć animację i pozostać w aktualnym stanie (.aktualnie) lub przejść do stanu początkowego (.start) lub do stanu końcowego (.END)

Nawiasem mówiąc, można nawet zatrzymać i wznowić później ...

animator.pauseAnimation()
animator.startAnimation()

Uwaga: Jeśli nie chcesz nagłe odwołanie można odwrócić animację lub nawet zmienić animację po wstrzymać je!

Odpowiedział 09/11/2017 o 17:57
źródło użytkownik

głosy
7

Jeśli tylko chcesz, aby wstrzymać / zatrzymać animację płynnie

self.yourView.layer.speed = 0;

Źródło: Jak wstrzymać animację warstwy drzewa

Odpowiedział 29/06/2015 o 11:02
źródło użytkownik

głosy
5
[UIView setAnimationsEnabled:NO];
// your code here
[UIView setAnimationsEnabled:YES];
Odpowiedział 06/02/2015 o 05:30
źródło użytkownik

głosy
5

Żadne z powyższych rozwiązać go dla mnie, ale to pomogło: the UIViewanimation natychmiast ustawia właściwość, następnie ożywia go. Zatrzymuje animację gdy warstwa prezentacji pasuje do modelu (zbiór własności).

I rozwiązać mój problem, który był „Chcę animować skąd wyglądasz jak wyglądasz” ( „ty” oznacza pogląd). Jeśli chcesz, wtedy:

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

ustawić pozycję do warstwy prezentacji

Używam kilka opcji, w tym UIViewAnimationOptionOverrideInheritedDuration

Ale ponieważ dokumentacja Apple jest niejasne, nie wiem, czy to naprawdę przesłania inne animacje, kiedy używany, lub po prostu resetuje liczniki.

[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 które powinny być przyzwoite rozwiązanie na teraz.

Odpowiedział 16/08/2011 o 18:21
źródło użytkownik

głosy
1

Mam ten sam problem; API nie mają nic do odwołania jakąś specyficzną animację.

+ (void)setAnimationsEnabled:(BOOL)enabled

Wyłącza wszystkie animacje, a tym samym nie działa dla mnie. Są dwa rozwiązania:

1) dokonać animowany obiekt podrzędny. Potem, gdy chcesz zrezygnować z animacji dla tego widoku, należy usunąć widok lub ukryć. Bardzo proste, ale trzeba odtworzyć podrzędny bez animacji, jeśli trzeba trzymać go w polu widzenia.

2) powtórzyć anim tylko jeden, i dokonać wyboru delegata, aby ponownie uruchomić anim razie potrzeby, na przykład:

-(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 z 2) jest to, że zawsze opóźnić zatrzymanie anim gdyż zakończy bieżący cykl animacji.

Mam nadzieję że to pomoże.

Odpowiedział 08/05/2009 o 18:03
źródło użytkownik

głosy
0

Żaden z odpowiedzieli rozwiązań pracował dla mnie. I rozwiązać moje problemy w ten sposób (nie wiem, czy jest to prawidłowy sposób?), Ponieważ miałem problemy podczas wywoływania tego zbyt szybko (gdy poprzednia animacja nie był jeszcze gotowy). Mijam mój poszukiwanych animację z customAnim bloku.

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

    }

}
Odpowiedział 20/08/2019 o 14:52
źródło użytkownik

głosy
0

Kiedy pracuję z UIStackViewanimacją, oprócz removeAllAnimations()muszę ustawić pewne wartości do początkowego ponieważ removeAllAnimations()można ustawić je do stanu nieprzewidywalny. Mam stackViewz view1i view2wewnątrz, i jeden widok powinien być widoczny i jeden ukryty:

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)
}
Odpowiedział 07/02/2019 o 09:03
źródło użytkownik

głosy
0

Swift wersja rozwiązania Stephen Darlington

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

// set view properties
UIView.commitAnimations()
Odpowiedział 26/12/2017 o 15:09
źródło użytkownik

głosy
0

Aby wstrzymać animację bez powrotu do stanu oryginalnego lub końcowy:

CFTimeInterval paused_time = [myView.layer convertTime:CACurrentMediaTime() fromLayer:nil];
myView.layer.speed = 0.0;
myView.layer.timeOffset = paused_time;
Odpowiedział 03/12/2015 o 21:43
źródło użytkownik

głosy
0
CALayer * pLayer = self.layer.presentationLayer;
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView animateWithDuration:0.001 animations:^{
    self.frame = pLayer.frame;
}];
Odpowiedział 28/01/2013 o 15:54
źródło użytkownik

głosy
0

Nawet jeśli anulować animację w sposób wyżej animacji didStopSelectornadal działa. Więc jeśli masz stanów logicznych w aplikacji napędzane przez animacji będziesz mieć problemy. Z tego powodu ze sposobów opisanych powyżej Używam zmienną kontekstowe UIViewanimacji. Jeśli zdasz aktualny stan swojego programu przez param kontekstowego do animacji, gdy animacja zatrzymuje swoją didStopSelectorfunkcję może zdecydować, czy należy coś zrobić lub po prostu wrócić na podstawie aktualnego stanu i wartości stanu przekazanego jako kontekst.

Odpowiedział 05/10/2010 o 09:52
źródło użytkownik

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