Mam warstwę ze złożonym kodem rysunkowym w metodzie -drawInContext:. Próbuję zminimalizować ilość rysowania, które muszę zrobić, więc używam -setNeedsDisplayInRect: do aktualizacji tylko zmienionych części. To działa świetnie. Jednak gdy system graficzny aktualizuje moją warstwę, przechodzi ze starego do nowego obrazu przy użyciu efektu przenikania. Chciałbym, żeby przełączało się natychmiast.
Próbowałem użyć CATransaction, aby wyłączyć akcje i ustawić czas trwania na zero, ale żadna z nich nie działa. Oto kod, którego używam:
[CATransaction begin];
[CATransaction setDisableActions: YES];
[self setNeedsDisplayInRect: rect];
[CATransaction commit];
Czy istnieje inna metoda na CATransaction, której powinienem użyć zamiast tego (próbowałem również -setValue: forKey: z kCATransactionDisableActions, ten sam wynik).
iphone
ios
core-animation
calayer
Ben Gottlieb
źródło
źródło
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });
Odpowiedzi:
Możesz to zrobić, ustawiając słownik akcji na warstwie, aby powracał
[NSNull null]
jako animacja dla odpowiedniego klucza. Na przykład używamaby wyłączyć animacje pojawiania się / zanikania podczas wstawiania lub zmiany podwarstw w jednej z moich warstw, a także zmiany rozmiaru i zawartości warstwy. Uważam, że
contents
kluczem jest ten, którego szukasz, aby zapobiec przenikaniu na zaktualizowanym rysunku.Wersja Swift:
źródło
@"position"
klucza.@"hidden"
właściwość również do słownika akcji, jeśli przełączasz w ten sposób widoczność warstwy i chcesz wyłączyć animację krycia.actionForKey:
zamiast), odkrywającfontSize
,contents
,onLayout
ibounds
. Wygląda na to, że możesz określić dowolny klucz, którego możesz użyć wsetValue:forKey:
metodzie, w rzeczywistości określając złożone ścieżki kluczy, takie jakbounds.size
.Również:
źródło
//foo
z[self setNeedsDisplayInRect: rect]; [self displayIfNeeded];
odpowiedzieć na oryginalne pytanie.[CATransaction setDisableActions:YES]
[CATransaction setDisableActions:YES]
jest skrótem dla samej[CATransaction setValue:forKey:]
linii. Nadal potrzebujesz liniibegin
icommit
.Po zmianie właściwości warstwy ośrodek CA zwykle tworzy niejawny obiekt transakcji, aby ożywić zmianę. Jeśli nie chcesz animować zmiany, możesz wyłączyć niejawne animacje, tworząc jawną transakcję i ustawiając jej właściwość kCATransactionDisableActions na wartość true .
Cel C
Szybki
źródło
Oprócz odpowiedzi Brada Larsona : dla warstw niestandardowych (które są tworzone przez Ciebie) możesz użyć delegowania zamiast modyfikowania
actions
słownika warstwy . To podejście jest bardziej dynamiczne i może być bardziej wydajne. I umożliwia wyłączenie wszystkich niejawnych animacji bez konieczności wyszczególniania wszystkich animowanych klawiszy.Niestety, nie można używać
UIView
s jako delegatów warstwy niestandardowej, ponieważ każda z nichUIView
jest już delegatem swojej własnej warstwy. Ale możesz użyć prostej klasy pomocniczej, takiej jak ta:Zastosowanie (wewnątrz widoku):
Czasami wygodnie jest mieć kontroler widoku jako delegata dla niestandardowych podwarstw widoku; w tym przypadku nie ma potrzeby stosowania klasy pomocniczej, można zaimplementować
actionForLayer:forKey:
metodę bezpośrednio w kontrolerze.Ważna uwaga: nie próbuj modyfikować delegata
UIView
warstwy bazowej (np. Aby włączyć niejawne animacje) - zdarzają się złe rzeczy :)Uwaga: jeśli chcesz animować (nie wyłączać animacji) przerysowania warstw, nie ma sensu umieszczać
[CALayer setNeedsDisplayInRect:]
wywołania wewnątrz aCATransaction
, ponieważ faktyczne przerysowanie może (i prawdopodobnie nastąpi) później. Dobrym podejściem jest użycie właściwości niestandardowych, jak opisano w tej odpowiedzi .źródło
CALayer
co uniemożliwiłonoImplicitAnimations
pracę. Może powinieneś oznaczyć swoją odpowiedź jako poprawną i wyjaśnić, co było nie tak z tą warstwą?CALayer
instancją (miałem wtedy dwie).NSNull
nie implementujeCAAction
protokołu i nie jest to protokół, który ma tylko opcjonalne metody. Ten kod również ulega awarii i nie można tego nawet przetłumaczyć na szybkość. Lepsze rozwiązanie: spraw, aby obiekt był zgodny zCAAction
protokołem (z pustąrunActionForKey:object:arguments:
metodą, która nic nie robi) i zwróćself
zamiast[NSNull null]
. Ten sam efekt, ale bezpieczny (na pewno nie ulegnie awarii) i działa również w Swift.Oto bardziej wydajne rozwiązanie, podobne do akceptowanej odpowiedzi, ale dla Swift . W niektórych przypadkach będzie to lepsze niż tworzenie transakcji za każdym razem, gdy modyfikujesz wartość, która ma wpływ na wydajność, jak wspominali inni, np. Częsty przypadek użycia przeciągania pozycji warstwy przy 60 klatkach na sekundę.
Zobacz dokumentację Apple, aby dowiedzieć się, jak rozwiązuje się działania warstw . Zaimplementowanie delegata spowodowałoby pominięcie jeszcze jednego poziomu w kaskadzie, ale w moim przypadku było to zbyt bałagan z powodu zastrzeżenia dotyczącego delegata, który musi być ustawiony na skojarzony UIView .
Edycja: Zaktualizowano dzięki komentatorowi wskazującemu, że
NSNull
jest zgodny zCAAction
.źródło
NullAction
for Swift,NSNull
jestCAAction
już zgodne, więc możesz zrobić to samo, co w celu C: layer.actions = ["position": NSNull ()]W oparciu o odpowiedź Sama i trudności Simona ... dodaj odwołanie delegata po utworzeniu CSShapeLayer:
... w innym miejscu w pliku „m” ...
Zasadniczo to samo, co u Sama, bez możliwości przełączania się za pomocą niestandardowego układu zmiennych „disableImplicitAnimations”. Bardziej podejście „sztywnego drutu”.
źródło
Właściwie nie znalazłem żadnej odpowiedzi jako właściwej. Metoda, która rozwiązuje ten problem była dla mnie następująca:
Wtedy możesz dowolną logikę, aby wyłączyć określoną animację, ale ponieważ chciałem je wszystkie usunąć, zwróciłem zero.
źródło
Aby wyłączyć niejawne animacje warstw w Swift
źródło
disableActions()
bo wygląda na to, że robi to samo, ale tak naprawdę jest to, aby uzyskać bieżącą wartość. Myślę, że to też jest zaznaczone@discardable
, przez co trudniej to zauważyć. Źródło: developer.apple.com/documentation/quartzcore/catransaction/…Dowiedział się prostszą metodę do działania wyłączyć Wewnątrz
CATransaction
że wewnętrznie wzywasetValue:forKey:
dokCATransactionDisableActions
klucza:Szybki:
źródło
Dodaj to do swojej klasy niestandardowej, w której implementujesz metodę -drawRect (). Wprowadź zmiany w kodzie, aby dostosować go do swoich potrzeb, dla mnie „krycie” wystarczyło, aby zatrzymać animację przechodzenia.
źródło
Jeśli kiedykolwiek będziesz potrzebować bardzo szybkiej (ale wprawdzie hakerskiej) poprawki, warto po prostu zrobić (Swift):
źródło
view.layer?.actions = [:]
tak naprawdę nie działa. Ustawienie prędkości jest brzydkie, ale działa.Zaktualizowano w celu szybkiego i wyłączenia tylko jednej niejawnej animacji właściwości w systemie iOS, a nie w systemie MacOS
Inny przykład, w tym przypadku eliminacja dwóch niejawnych animacji.
źródło
Od iOS 7 istnieje wygodna metoda, która robi to:
źródło
Aby wyłączyć irytującą (rozmytą) animację podczas zmiany właściwości ciągu CATextLayer, możesz to zrobić:
a następnie użyj go w ten sposób (nie zapomnij odpowiednio ustawić CATextLayer, np. poprawnej czcionki itp.):
Możesz zobaczyć moją pełną konfigurację CATextLayer tutaj:
Teraz możesz aktualizować caTextLayer.string tyle, ile chcesz =)
Zainspirowany tym i tą odpowiedzią.
źródło
Spróbuj tego.
Ostrzeżenie
Jeśli ustawisz delegata instancji UITableView, czasami zdarzają się awarie (prawdopodobnie najczęstszy przewijany widok nazywa się rekurencyjnie).
źródło