Ruch oparty na fizyce jest napędzany siłą. Siła naprężenia to jedna z sił, które wpływają na interaktywność i ruch. Siła naprężenia ma te właściwości: tłumienie i sztywność. W animacji opartej na sprężynie wartość i prędkość są obliczane na podstawie siły sprężyny, która jest stosowana w każdej klatce.
Jeśli chcesz, aby animacje w aplikacji zwalniały tylko w jednym kierunku, rozważ użycie animacji przesunięcia opartej na tarciu.
Cykl życia animacji sprężynowej
W animacji opartej na sprężynie klasa SpringForce
umożliwia dostosowanie sztywności sprężyny, współczynnika tłumienia i pozycji końcowej. Gdy tylko animacja się rozpocznie, siła sprężyny będzie aktualizować wartość animacji i prędkość w każdej klatce. Animacja trwa, dopóki siła sprężyny nie osiągnie stanu równowagi.
Jeśli na przykład przeciągniesz ikonę aplikacji po ekranie, a potem ją puścisz, podnosząc palec, ikona wróci na swoje pierwotne miejsce pod wpływem niewidocznej, ale znanej siły.
Rysunek 1 przedstawia podobny efekt sprężyny. Znak plusa (+) na środku okręgu wskazuje siłę nacisku wywieranego przez gest dotykowy.
Tworzenie animacji sprężynowej
Ogólne kroki tworzenia animacji sprężynowej w aplikacji są następujące:
- Dodaj bibliotekę pomocy Aby używać klas animacji sprężynowych, musisz dodać do projektu bibliotekę pomocy.
- Utwórz animację sprężynową:
głównym krokiem jest utworzenie instancji klasy
SpringAnimationi ustawienie parametrów zachowania ruchu. - (Opcjonalnie) Zarejestruj detektory:
zarejestruj detektory, aby śledzić zmiany w cyklu życia animacji i aktualizacje wartości animacji.
Uwaga: odbiornik aktualizacji należy zarejestrować tylko wtedy, gdy potrzebujesz aktualizacji wartości animacji w każdej klatce. Listener aktualizacji zapobiega potencjalnemu uruchomieniu animacji w osobnym wątku.
- (Opcjonalnie) Usuń odbiorców: usuń odbiorców, którzy nie są już używani.
- (Opcjonalnie) Ustaw wartość początkową: Dostosuj wartość początkową animacji.
- (Opcjonalnie) Ustaw zakres wartości: Ustaw zakres wartości animacji, aby ograniczyć wartości do zakresu minimalnego i maksymalnego.
- (Opcjonalnie) Ustaw prędkość początkową: ustaw prędkość początkową animacji.
- (Opcjonalnie) Ustaw właściwości sprężyny: Ustaw współczynnik tłumienia i sztywność sprężyny.
- (Opcjonalnie) Utwórz niestandardową sprężynę: utwórz niestandardową sprężynę, jeśli nie chcesz używać domyślnej sprężyny lub chcesz używać wspólnej sprężyny w całej animacji.
- Uruchom animację: Uruchamia animację sprężynową.
- (Opcjonalnie) Anuluj animację: anuluj animację, jeśli użytkownik nagle zamknie aplikację lub widok stanie się niewidoczny.
W kolejnych sekcjach szczegółowo omówimy ogólne etapy tworzenia animacji sprężynowej.
Dodawanie biblioteki pomocy
Aby używać biblioteki pomocy opartej na fizyce, musisz dodać ją do projektu w ten sposób:
- Otwórz plik
build.gradlemodułu aplikacji. Dodaj bibliotekę pomocy do sekcji
dependencies.Dynamiczny
dependencies { def dynamicanimation_version = '1.0.0' implementation "androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version" }
Kotlin
dependencies { val dynamicanimation_version = "1.0.0" implementation("androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version") }
Aby wyświetlić bieżące wersje tej biblioteki, zapoznaj się z informacjami o bibliotece Dynamic Animation na stronie wersji.
Tworzenie animacji sprężynowej
Klasa SpringAnimation umożliwia tworzenie animacji sprężynowej dla obiektu. Aby utworzyć animację sprężynową, musisz utworzyć instancję klasy SpringAnimation i podać obiekt, właściwość obiektu, którą chcesz animować, oraz opcjonalną końcową pozycję sprężyny, w której animacja ma się zatrzymać.
Uwaga: podczas tworzenia animacji sprężyny końcowa pozycja sprężyny jest opcjonalna. Musi być jednak zdefiniowana przed rozpoczęciem animacji.
Kotlin
val springAnim = findViewById<View>(R.id.imageView).let { img -> // Setting up a spring animation to animate the view’s translationY property with the final // spring position at 0. SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0f) }
Java
final View img = findViewById(R.id.imageView); // Setting up a spring animation to animate the view’s translationY property with the final // spring position at 0. final SpringAnimation springAnim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0);
Animacja oparta na sprężynie może animować widoki na ekranie, zmieniając rzeczywiste właściwości w obiektach widoku. W systemie dostępne są te widoki:
ALPHA: Represents the alpha transparency on the view. Domyślnie wartość wynosi 1 (nieprzezroczysty), a wartość 0 oznacza pełną przezroczystość (niewidoczny).TRANSLATION_X,TRANSLATION_YiTRANSLATION_Z: te właściwości określają położenie widoku jako odchylenie od jego współrzędnych po lewej stronie, u góry i wysokości, które są ustawiane przez kontener układu.TRANSLATION_Xopisuje współrzędną po lewej stronie.TRANSLATION_Yopisuje współrzędną górną.TRANSLATION_Zokreśla głębokość widoku w stosunku do jego wysokości.
ROTATION,ROTATION_XiROTATION_Y: te właściwości kontrolują obrót w 2D (właściwośćrotation) i 3D wokół punktu obrotu.SCROLL_XiSCROLL_Y: te właściwości wskazują przesunięcie przewijania lewej i górnej krawędzi źródła w pikselach. Wskazuje też pozycję w odniesieniu do tego, jak bardzo strona jest przewinięta.SCALE_XiSCALE_Y: te właściwości kontrolują skalowanie 2D widoku wokół jego punktu obrotu.X,YiZ: są to podstawowe właściwości narzędziowe opisujące ostateczną lokalizację widoku w jego kontenerze.Xto suma wartości po lewej stronie iTRANSLATION_X.Yto suma wartości najwyższej iTRANSLATION_Y.Zto suma wartości wysokości iTRANSLATION_Z.
Rejestrowanie detektorów
Klasa DynamicAnimation udostępnia 2 słuchaczy: OnAnimationUpdateListener i OnAnimationEndListener.
Te odbiorniki nasłuchują aktualizacji animacji, np. gdy zmienia się wartość animacji lub gdy animacja się kończy.
OnAnimationUpdateListener
Jeśli chcesz animować wiele widoków, aby utworzyć animację łańcuchową, możesz skonfigurować OnAnimationUpdateListener tak, aby otrzymywać wywołanie zwrotne za każdym razem, gdy zmieni się właściwość bieżącego widoku. Wywołanie zwrotne powiadamia inny widok o konieczności zaktualizowania pozycji sprężyny na podstawie zmiany wprowadzonej we właściwości bieżącego widoku. Aby zarejestrować odbiorcę, wykonaj te czynności:
-
Wywołaj metodę
addUpdateListener()i dołącz słuchacza do animacji.Uwaga: musisz zarejestrować odbiorcę aktualizacji, zanim rozpocznie się animacja. Jednak odbiornik aktualizacji należy zarejestrować tylko wtedy, gdy potrzebujesz aktualizacji wartości animacji w każdej klatce. Listener aktualizacji zapobiega potencjalnemu uruchomieniu animacji w osobnym wątku.
-
Zastąp metodę
onAnimationUpdate(), aby powiadomić wywołującego o zmianie w bieżącym obiekcie. Poniższy przykładowy kod ilustruje ogólne użycieOnAnimationUpdateListener.
Kotlin
// Setting up a spring animation to animate the view1 and view2 translationX and translationY properties val (anim1X, anim1Y) = findViewById<View>(R.id.view1).let { view1 -> SpringAnimation(view1, DynamicAnimation.TRANSLATION_X) to SpringAnimation(view1, DynamicAnimation.TRANSLATION_Y) } val (anim2X, anim2Y) = findViewById<View>(R.id.view2).let { view2 -> SpringAnimation(view2, DynamicAnimation.TRANSLATION_X) to SpringAnimation(view2, DynamicAnimation.TRANSLATION_Y) } // Registering the update listener anim1X.addUpdateListener { _, value, _ -> // Overriding the method to notify view2 about the change in the view1’s property. anim2X.animateToFinalPosition(value) } anim1Y.addUpdateListener { _, value, _ -> anim2Y.animateToFinalPosition(value) }
Java
// Creating two views to demonstrate the registration of the update listener. final View view1 = findViewById(R.id.view1); final View view2 = findViewById(R.id.view2); // Setting up a spring animation to animate the view1 and view2 translationX and translationY properties final SpringAnimation anim1X = new SpringAnimation(view1, DynamicAnimation.TRANSLATION_X); final SpringAnimation anim1Y = new SpringAnimation(view1, DynamicAnimation.TRANSLATION_Y); final SpringAnimation anim2X = new SpringAnimation(view2, DynamicAnimation.TRANSLATION_X); final SpringAnimation anim2Y = new SpringAnimation(view2, DynamicAnimation.TRANSLATION_Y); // Registering the update listener anim1X.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() { // Overriding the method to notify view2 about the change in the view1’s property. @Override public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value, float velocity) { anim2X.animateToFinalPosition(value); } }); anim1Y.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() { @Override public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value, float velocity) { anim2Y.animateToFinalPosition(value); } });
OnAnimationEndListener
OnAnimationEndListener
powiadamia o zakończeniu animacji. Możesz skonfigurować odbiornik tak, aby otrzymywał wywołanie zwrotne, gdy animacja osiągnie stan równowagi lub zostanie anulowana. Aby zarejestrować odbiornik, wykonaj te czynności:
-
Wywołaj metodę
addEndListener()i dołącz słuchacza do animacji. -
Zastąp metodę
onAnimationEnd(), aby otrzymywać powiadomienia, gdy animacja osiągnie stan równowagi lub zostanie anulowana.
Usuwanie detektorów
Aby przestać otrzymywać wywołania zwrotne dotyczące aktualizacji animacji i wywołania zwrotne dotyczące zakończenia animacji, wywołaj odpowiednio metody removeUpdateListener() i removeEndListener().
Ustawianie wartości początkowej animacji
Aby ustawić wartość początkową animacji, wywołaj metodę
setStartValue()
i przekaż wartość początkową animacji. Jeśli nie ustawisz wartości początkowej, animacja użyje bieżącej wartości właściwości obiektu jako wartości początkowej.
Ustawianie zakresu wartości animacji
Jeśli chcesz ograniczyć wartość właściwości do określonego zakresu, możesz ustawić minimalną i maksymalną wartość animacji. Pomaga też kontrolować zakres w przypadku animowania właściwości, które mają zakres wewnętrzny, np. przezroczystość (od 0 do 1).
-
Aby ustawić wartość minimalną, wywołaj metodę
setMinValue()i przekaż minimalną wartość właściwości. -
Aby ustawić wartość maksymalną, wywołaj metodę
setMaxValue()i przekaż maksymalną wartość właściwości.
Obie metody zwracają animację, dla której ustawiana jest wartość.
Uwaga: jeśli ustawisz wartość początkową i określisz zakres wartości animacji, upewnij się, że wartość początkowa mieści się w zakresie wartości minimalnej i maksymalnej.
Ustaw prędkość początkową
Prędkość początkowa określa szybkość, z jaką właściwość animacji zmienia się na początku animacji. Domyślna prędkość początkowa to zero pikseli na sekundę. Prędkość możesz ustawić za pomocą prędkości gestów dotykowych lub użyć stałej wartości jako prędkości początkowej. Jeśli zdecydujesz się podać stałą wartość, zalecamy określenie jej w jednostkach dp na sekundę, a następnie przekonwertowanie jej na piksele na sekundę. Określenie wartości w pikselach niezależnych od gęstości na sekundę pozwala na niezależność prędkości od gęstości i formatów. Więcej informacji o przeliczaniu wartości na piksele na sekundę znajdziesz w sekcji Przeliczanie dp na sekundę na piksele na sekundę.
Aby ustawić prędkość, wywołaj metodę
setStartVelocity()
i przekaż prędkość w pikselach na sekundę. Metoda zwraca obiekt siły sprężystości, w którym ustawiono prędkość.
Uwaga: do pobierania i obliczania prędkości gestów dotykowych używaj metod klasy GestureDetector.OnGestureListener lub VelocityTracker.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Compute velocity in the unit pixel/second vt.computeCurrentVelocity(1000) val velocity = vt.yVelocity setStartVelocity(velocity) } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Compute velocity in the unit pixel/second vt.computeCurrentVelocity(1000); float velocity = vt.getYVelocity(); anim.setStartVelocity(velocity);
Przekształcanie dp na sekundę na piksele na sekundę
Prędkość sprężyny musi być podana w pikselach na sekundę. Jeśli zdecydujesz się podać stałą wartość jako początek prędkości, podaj ją w dp na sekundę, a następnie przekonwertuj na piksele na sekundę. W przypadku konwersji użyj metody
applyDimension()
z klasy TypedValue. Zapoznaj się z poniższym przykładowym kodem:
Kotlin
val pixelPerSecond: Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, resources.displayMetrics)
Java
float pixelPerSecond = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, getResources().getDisplayMetrics());
Ustawianie właściwości sprężyny
Klasa SpringForce definiuje metody pobierania i ustawiania każdej właściwości sprężyny, np. współczynnika tłumienia i sztywności. Aby ustawić właściwości sprężyny, musisz pobrać obiekt siły sprężystości lub utworzyć niestandardową siłę sprężystości, w której możesz ustawić właściwości. Więcej informacji o tworzeniu niestandardowej siły sprężystości znajdziesz w sekcji Tworzenie niestandardowej siły sprężystości.
Wskazówka: podczas korzystania z metod ustawiających możesz utworzyć łańcuch metod, ponieważ wszystkie metody ustawiające zwracają obiekt siły sprężystej.
Współczynnik tłumienia
Współczynnik tłumienia opisuje stopniowe zmniejszanie się oscylacji sprężyny. Za pomocą współczynnika tłumienia możesz określić, jak szybko drgania zanikają z jednego odbicia do drugiego. Sprężynę można wytłumić na 4 sposoby:
- Nadmierne tłumienie występuje, gdy współczynnik tłumienia jest większy niż 1. Pozwala to na delikatne powrócenie obiektu do pozycji spoczynkowej.
- Tłumienie krytyczne występuje, gdy współczynnik tłumienia jest równy 1. Pozwala to obiektowi wrócić do pozycji spoczynkowej w najkrótszym czasie.
- Niedotłumienie występuje, gdy współczynnik tłumienia jest mniejszy niż 1. Pozwala on obiektowi wielokrotnie przekraczać pozycję spoczynkową, a następnie stopniowo ją osiągać.
- Nietłumione występuje, gdy współczynnik tłumienia jest równy zero. Pozwala to obiektowi oscylować w nieskończoność.
Aby dodać do sprężyny współczynnik tłumienia, wykonaj te czynności:
-
Wywołaj metodę
getSpring(), aby pobrać sprężynę i dodać współczynnik tłumienia. -
Wywołaj metodę
setDampingRatio()i przekaż współczynnik tłumienia, który chcesz dodać do sprężyny. Metoda zwraca obiekt siły sprężystości, w którym ustawiono współczynnik tłumienia.Uwaga: współczynnik tłumienia musi być liczbą nieujemną. Jeśli ustawisz współczynnik tłumienia na zero, sprężyna nigdy nie osiągnie pozycji spoczynkowej. Innymi słowy, oscyluje w nieskończoność.
W systemie dostępne są te stałe współczynnika tłumienia:
DAMPING_RATIO_HIGH_BOUNCYDAMPING_RATIO_MEDIUM_BOUNCYDAMPING_RATIO_LOW_BOUNCYDAMPING_RATIO_NO_BOUNCY
Rysunek 2. Wysoki współczynnik odrzuceń
Ilustracja 3. Średnie odbicie
Rysunek 4. Niski współczynnik odrzuceń
Rysunek 5. Brak odbicia
Domyślny współczynnik tłumienia to DAMPING_RATIO_MEDIUM_BOUNCY.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Setting the damping ratio to create a low bouncing effect. spring.dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Setting the damping ratio to create a low bouncing effect. anim.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY); …
Sztywność
Sztywność określa stałą sprężystości, która mierzy siłę sprężyny. Sztywna sprężyna wywiera większą siłę na przymocowany do niej obiekt, gdy nie znajduje się w pozycji spoczynkowej. Aby dodać sztywność sprężyny, wykonaj te czynności:
-
Wywołaj metodę
getSpring(), aby pobrać sprężynę, która doda sztywności. -
Wywołaj metodę
setStiffness()i przekaż wartość sztywności, którą chcesz dodać do sprężyny. Metoda zwraca obiekt siły sprężystości, w którym ustawiono sztywność.Uwaga: sztywność musi być liczbą dodatnią.
W systemie dostępne są te stałe sztywności:
Rysunek 6. Wysoka sztywność
Rysunek 7. Średnia sztywność
Rysunek 8. Niska sztywność
Rysunek 9. Bardzo mała sztywność
Domyślna sztywność to STIFFNESS_MEDIUM.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Setting the spring with a low stiffness. spring.stiffness = SpringForce.STIFFNESS_LOW … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Setting the spring with a low stiffness. anim.getSpring().setStiffness(SpringForce.STIFFNESS_LOW); …
Tworzenie niestandardowej siły sprężystości
Możesz utworzyć niestandardową siłę sprężyny zamiast domyślnej. Niestandardowa siła sprężyny umożliwia udostępnianie tego samego wystąpienia siły sprężyny w wielu animacjach sprężyny. Po utworzeniu siły sprężystości możesz ustawić właściwości takie jak współczynnik tłumienia i sztywność.
-
Utwórz obiekt
SpringForce.SpringForce force = new SpringForce(); -
Przypisz właściwości, wywołując odpowiednie metody. Możesz też utworzyć łańcuch metod.
force.setDampingRatio(DAMPING_RATIO_LOW_BOUNCY).setStiffness(STIFFNESS_LOW); -
Aby ustawić sprężynę animacji, wywołaj metodę
setSpring().setSpring(force);
Uruchom animację
Animację sprężynową możesz rozpocząć na 2 sposoby: wywołując metodę start() lub animateToFinalPosition(). Obie metody muszą być wywoływane w wątku głównym.
animateToFinalPosition()
wykonuje 2 zadania:
- Ustawia końcową pozycję sprężyny.
- Rozpoczyna animację, jeśli nie została jeszcze uruchomiona.
Metoda ta aktualizuje ostateczną pozycję sprężyny i w razie potrzeby rozpoczyna animację, więc możesz ją wywołać w dowolnym momencie, aby zmienić przebieg animacji. Na przykład w animacji sprężynowej połączonej w łańcuch animacja jednego widoku zależy od innego widoku. W przypadku takiej animacji wygodniej jest użyć metody animateToFinalPosition(). Jeśli użyjesz tej metody w animacji sprężynowej z połączonymi elementami, nie musisz się martwić, czy animacja, którą chcesz zaktualizować, jest obecnie uruchomiona.
Ilustracja 10 przedstawia animację sprężynową łańcuchową, w której animacja jednego widoku zależy od innego widoku.
Aby użyć metody animateToFinalPosition(), wywołaj metodę animateToFinalPosition() i przekaż pozycję spoczynkową sprężyny. Możesz też ustawić pozycję spoczynkową sprężyny, wywołując metodę setFinalPosition().
Metoda start() nie ustawia od razu wartości właściwości na wartość początkową. Wartość właściwości zmienia się przy każdym impulsie animacji, który występuje przed etapem rysowania.
Dzięki temu zmiany są odzwierciedlane w kolejnej klatce, tak jakby wartości były ustawiane od razu.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Starting the animation start() … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Starting the animation anim.start(); …
Anulowanie animacji
Możesz anulować animację lub przejść do jej końca. Idealna sytuacja, w której musisz anulować animację lub przejść do jej końca, to taka, gdy interakcja użytkownika wymaga natychmiastowego zakończenia animacji. Dzieje się to najczęściej, gdy użytkownik nagle zamknie aplikację lub widok stanie się niewidoczny.
Animację można zakończyć na 2 sposoby.
Metoda cancel() kończy animację w miejscu, w którym się znajduje. Metoda skipToEnd() pomija animację do wartości końcowej, a następnie ją kończy.
Zanim zakończysz animację, sprawdź stan sprężyny. Jeśli stan jest nietłumiony, animacja nigdy nie osiągnie pozycji spoczynkowej.
Aby sprawdzić stan sprężyny, wywołaj metodę canSkipToEnd(). Jeśli sprężyna jest tłumiona, metoda zwraca true, w przeciwnym razie false.
Gdy poznasz stan sprężyny, możesz zakończyć animację za pomocą metody skipToEnd() lub cancel(). Metodę cancel() należy wywoływać tylko w głównym wątku.
Uwaga: metoda
skipToEnd() powoduje zwykle
skok wizualny.