Jak natychmiast przenieść CALayer (bez animacji)


80

Próbuję przeciągnąć CALayerw aplikacji na iOS.

Jak tylko zmienię właściwość position, próbuje animować do nowej pozycji i miga w każdym miejscu:

 layer.position = CGPointMake(x, y)

Jak mogę CALayersnatychmiast się przenieść ? Nie mogę się rozejrzeć po interfejsie API Core Animation.


w odniesieniu do tej bardzo starej kontroli jakości, krytyczny problem na dzień dzisiejszy jest następujący: stackoverflow.com/a/56980329/294884
Fattie,

Odpowiedzi:


168

Chcesz zakończyć rozmowę w następujący sposób:

[CATransaction begin]; 
[CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions];
layer.position = CGPointMake(x, y);
[CATransaction commit];

1
To jest dokładnie to. Nawet nie pomyślałem o CATransaction. Wielkie dzięki!
Mel

5
Tak, 6 i pół roku później. Wciąż pomocny. : D
Fogmeister

1
iOS7 obsługuje nowe skróty:[UIView performWithoutAnimation:<#^(void)actionsWithoutAnimation#>];
k06a

2
7 lat, 7 miesięcy i 17 dni później: nadal pomocne. Dzięki!
kanobius

1
kciuk w górę 9 lat później
nshuman

32

Rozszerzenie Swift 3:

extension CALayer {
    class func performWithoutAnimation(_ actionsWithoutAnimation: () -> Void){
        CATransaction.begin()
        CATransaction.setValue(true, forKey: kCATransactionDisableActions)
        actionsWithoutAnimation()
        CATransaction.commit()
    }
}

Stosowanie :

CALayer.performWithoutAnimation(){
    someLayer.position = newPosition
}

1
Przydatne jest dodanie @noescapeatrybutu do bloku, aby zezwolić (i wyjaśnić), że selfnie jest potrzebny w bloku
Andrew

22

Możesz także skorzystać z funkcji komfortowej

[CATransaction setDisableActions:YES] 

także.

Uwaga: koniecznie przeczytaj komentarze Yogeva Shelly, aby zrozumieć wszelkie pułapki, które mogą wystąpić.


5
Ważne, ma to wpływ na wszystkie CALayer, więc chcesz ponownie włączyć akcje po zakończeniu, np. [CATransaction setDisableActions: YES]
Yogev Shelly

Cholera, powinienem to powiedzieć. Dobra obrona. Polecenie wyłącza animacje, dopóki nie zostanie ustawione na NIE lub dopóki główny silnik animacji graficznej nie zakończy cyklu pracy. Nie jestem pewien, czy to właściwe słowo: / Ale dziękuję za wyjaśnienie tego wszystkim.
Biclops,

15

Jak sugerowali inni, możesz użyć CATransaction.
Problem pojawia się, ponieważ CALayer ma domyślny niejawny czas trwania animacji wynoszący 0,25 sekundy.

W związku z tym łatwiejszą (moim zdaniem) alternatywą setDisableActionsjest użycie setAnimationDurationz wartością 0.0.

[CATransaction begin];
[CATransaction setAnimationDuration:0.0];
layer.position = CGPointMake(x, y);
[CATransaction commit];

Łatwe do zapamiętania, łatwe do zrozumienia podczas ponownego czytania kodu i łatwiejsze do wpisania. Dzięki!
Pan T

3

Łącząc poprzednie odpowiedzi tutaj dla Swift 4, aby wyraźnie określić czas trwania animacji ...

extension CALayer
{
    class func perform(withDuration duration: Double, actions: () -> Void) {
        CATransaction.begin()
        CATransaction.setAnimationDuration(duration)
        actions()
        CATransaction.commit()
    }
}

Stosowanie...

CALayer.perform(withDuration: 0.0) {
            aLayer.frame = aFrame
        }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.