2012-10-31 12 views
7

Przeczytałem o Property Animation i Hardware Acceleration, ale wciąż nie jestem pewien, jaki jest najbardziej efektywny sposób korzystania z klas animatora. (W związku z tym pytaniem nie muszę obsługiwać urządzeń przed Honeycomb, dlatego chcę używać klas animatorów.)Jaki jest optymalny sposób animowania rysowania w widoku przy użyciu klas animatora?

Załóżmy na przykład, że mam widok. W tym widoku mam BitmapDrawable, które chcę zanikać. Istnieje również wiele innych elementów w widoku, które się nie zmienią.

Jakiej właściwości lub obiektu najlepiej użyć w animatorze? Rysowanie? Farba, z której rysuję mapę bitową za pomocą onDraw? Coś innego?

Jak można to zrobić, aby zwiększyć wydajność przy akceleracji sprzętowej? Czy będzie to wymagało wywoływania unieważnienia dla każdego etapu animacji, czy istnieje sposób na animowanie tylko tego losowania i nie powodowanie, aby reszta widoku była przerysowana całkowicie dla każdego etapu animacji?

Domyślam się, że optymalnym przypadkiem byłoby, gdyby reszta widoku nie musiała być całkowicie przerysowana w oprogramowaniu, a raczej przyspieszenie sprzętowe skutecznie zanikające w losowaniu.

Jakieś sugestie lub wskazówki do zalecanych podejść?

Dzięki!

+0

Cóż, myślę, że pytasz o to, ponieważ powoduje kłopoty. Animacja prawdopodobnie unieważnia wszystko, ale możemy znaleźć obejście, jeśli pokażesz nam hierarchię widoku, którą posiadasz. Określ, w co się w nim animujesz. –

+0

Nie, jeszcze nic nie napisałem, próbuję uzyskać wszystkie informacje, zanim to zrobię. :) – cottonBallPaws

+0

Cóż, jeśli animacja działa dobrze na przeciętnych urządzeniach, to jesteśmy w porządku. Jeśli jednak jest zauważalnie ciężki, nawet po zwykłych udoskonaleniach, takich jak przyspieszanie sprzętowe (które może nie zawsze być dostępne), należy znaleźć własne rozwiązanie. Na przykład, jeśli animujesz tło powodujące unieważnienie całej hierarchii, utwórz migawkę hierarchii i animuj tło za nią. W każdym razie, to jest zasadniczo twoja decyzja, czy włożyć wysiłek, ponieważ prawdopodobnie będzie działać z akceleracją sprzętową i na większości urządzeń. (ufnie :) –

Odpowiedz

4

Za pomocą animatorów obiektów obiektowych są to po prostu funkcje matematyczne, które wielokrotnie wywołują metodę "setN()" co każde 10 milisekund, gdzie "N" jest właściwością, którą chcesz zmienić.

W przykładzie podanym w przypadku alfa oba wymagają wywołania do invalidate() w celu odtworzenia animowanego widoku. Różnica polegająca na tym, że wywołujesz setAlpha() na obiekcie View, wywołuje on dla ciebie invalidate(). Jeśli chcesz ustawić obiekt docelowy na obiekcie Paint, który jest używany do rysowania losowania, nadal musisz zadzwonić pod numer invalidate() na View, aby został przerysowany przy użyciu nowych parametrów Paint.

Idealnie chcesz ustawić cel na dziecko o najwyższym poziomie, aby można było przerysować tylko w widokach, które chcesz animować. Jeśli ustawisz cel w widoku głównym, na przykład wywoła on invalidate() na każde dziecko w całej grupie ViewGroup, które z kolei wywoła draw() na każde dziecko w ViewGroup. Jeśli ustawisz go na najwyższym poziomie, to tylko ImageView zostanie przerysowany.

Aby jak najlepiej wykorzystać Sprzęt, musisz użyć właściwości Warstwy. Najpierw musisz zdecydować, jaki będzie najwyższy nadrzędny widok, który chcesz animować. Jeśli chcesz tylko zaniknąć Drawable, będzie to Drawable lub zawierający View. Jeśli chcesz zniknąć wszystko, to będzie to widok główny. Cokolwiek zdecydujesz się na animację, zostanie zastosowane do całości na raz w postaci View.

Użyj setLayerType() w widoku nadrzędnym tuż przed uruchomieniem Animatora. Ustaw go na View#LAYER_TYPE_HARDWARE. Następnie ustaw AnimationListener i zresetuj typ LayerType na View#LAYER_TYPE_SOFTWARE lub View#LAYER_TYPE_NONE po zakończeniu animacji.

myParentView.setLayerType(View.LAYER_TYPE_HARDWARE, null); 
myObjectAnimator.addListener(new ViewAnimator.AnimatorListener() { 
    public void onAnimationEnd(Animator animation) { 
    myParentView.setLayerType(View.LAYER_TYPE_NONE); 
    } 
    public void onAnimationRepeat(Animator animation) { 
    } 
    public void onAnimationStart(Animator animation) { 
    } 
    public void onAnimationCancel(Animator animation) { 
    myParentView.setLayerType(View.LAYER_TYPE_NONE, null); 
    } 
} 
myObjectAnimator.start(); 

W tym przypadku, jeśli było tłumaczyć myParentView za pomocą właściwości translateX, to będzie można umieścić warstwę myParentView i wszystkich jego dzieci w jednej płaszczyźnie. Umieść go w pamięci sprzętowej. Przetłumacz cały widok na raz. Następnie, po zakończeniu, usuń z pamięci myParentView.

EDIT:

Ostatnia uwaga, Alpha sieje spustoszenie na CPU. Jeśli masz coś na pół-alfa i przetłumaczysz je w widoku, trudniej będzie je wyrenderować, niż po prostu przetłumaczyć widok. Używaj go oszczędnie.

1

Być może można nałożyć nowy widok (który zawiera tylko animator) na oryginalny. nowy widok ustawiony jest jako przezroczysty.

Reset, który powinieneś zrobić, jest nieprawidłowy w nowym widoku bez oryginalnego widoku.

1

Po przejrzeniu Twoich zapytań zasugeruję, proszę przejść przez ten standard document, który jest czysty, aby zrozumieć, jak prawidłowo używać invalidate(). Po drugie, Android API oferuje różne sposoby pracy z animacją w różnych sytuacjach.

Here, Mam nadzieję, że większość twoich wątpliwości zostanie usunięta. Proszę przejrzeć podsekcje i powiązany blog wspomniał o nich.

Mam nadzieję, że to ci pomoże.