Animuj ruch za pomocą fizyki sprężyny

Wypróbuj sposób tworzenia wiadomości
Jetpack Compose to zalecany zestaw narzędzi UI na Androida. Dowiedz się, jak korzystać z animacji w Compose

Na podstawie fizyki jest napędzane siłą. Siła sprężyny jest jedną z takich sił, między interakcją a ruchem. Siła sprężyny ma następujące właściwości: tłumienie i sztywność. W animacji typu sprężyna wartość oraz parametr prędkość jest obliczana na podstawie siły sprężystej zastosowanej do każdego ramki.

Jeśli chcesz, by animacje w aplikacji były spowolnione tylko w jednym kierunku, rozważ zastosowanie metody opartej na tarciu animacja przelotu .

Cykl życia animacji wiosennej

W wiosennej animacji SpringForce można dostosować sztywność, współczynnik tłumienia pozycji końcowej. Gdy tylko rozpocznie się animacja, siła sprężyny zostanie zaktualizowana wartość animacji i szybkość każdej klatki. Animacja będzie kontynuowana aż siła sprężyny osiągnie równowagę.

Na przykład, jeśli przeciągniesz ikonę aplikacji wokół ekranu, a później ją zwolnisz podniesienie palca od ikony spowoduje przywrócenie pierwotnej formy niewidzialną, ale znaną im siłą.

Rysunek 1 przedstawia podobny efekt wiosny. Znak plusa (+) na stronie środek okręgu wskazuje siłę wywieraną w wyniku gestu dotykowego.

Premiera wiosenna
Rysunek 1. Efekt wiosennej premiery
.

Tworzenie wiosennej animacji

Aby utworzyć wiosenną animację dla aplikacji, w następujący sposób:

W poniższych sekcjach opisano ogólne kroki budowy sprężyny z animacji.

Dodawanie biblioteki pomocy

Aby korzystać z biblioteki pomocy związanej z fizyką, musisz dodać do projektu bibliotekę pomocy w następujący sposób:

  1. Otwórz plik build.gradle modułu aplikacji.
  2. Dodaj bibliotekę pomocy do sekcji dependencies.

    Odlotowe

            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 na temat Dynamiczna animacja na stronie wersji.

Tworzenie animacji wiosennej

Zajęcia SpringAnimation umożliwiają tworzenie dla obiektu. Aby utworzyć wiosenną animację, musisz: utworzyć instancję SpringAnimation klasy i podaj obiekt, właściwość, którą chcesz animować, oraz parametr opcjonalna końcowa pozycja sprężyny, w której ma się spoczywać animacja.

Uwaga: podczas tworzenia wiosennej animacji końcowej położenie sprężyny jest opcjonalne. ale musi być zdefiniowany. 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ężynach może animować wyświetlenia na ekranie, zmieniając rzeczywiste właściwości w obiektach widoku. Następujące widoki są dostępne w system:

  • ALPHA: Reprezentuje przezroczystość widoku w wersji alfa. Wartość wynosi 1 (nieprzezroczysta) przez , gdzie wartość 0 oznacza pełną przezroczystość (niewidoczna).
  • TRANSLATION_X, TRANSLATION_Y i TRANSLATION_Z: te właściwości określają położenie widoku w postaci delta od jego lewej strony. współrzędnej, wysokości i wysokości, które są ustawiane przez układ kontenera.
  • ROTATION, ROTATION_X i ROTATION_Y: te właściwości sterują rotacją w 2D (usługa rotation) oraz Widok 3D wokół punktu obrotu.
  • SCROLL_X i SCROLL_Y: te właściwości wskazują przesunięcie przewijania źródła od lewej i od górnej krawędzi w pikselach. Wskazuje też pozycję strony, przewinięto.
  • SCALE_X i SCALE_Y: te sterują skalowaniem 2D widoku wokół jego punktu obrotu.
  • X, Y i Z: to są podstawowe kryteria właściwości użytkowych opisujące końcową lokalizację widoku kontenera.

Rejestrowanie detektorów

Klasa DynamicAnimation udostępnia 2 obiekty. słuchacze: OnAnimationUpdateListener i OnAnimationEndListener. Tacy słuchają aktualizacji w formie animacji, na przykład kiedy pojawia się zmiany wartości animacji i jej zakończenia.

Detektor OnAnimationUpdateListener

Jeśli chcesz animować wiele widoków, aby utworzyć łańcuchową animację, może skonfigurować: OnAnimationUpdateListener aby otrzymać telefon zwrotny za każdym razem, gdy nastąpi zmiana w bieżącym widoku usłudze. Wywołanie zwrotne powiadamia drugi widok, aby zaktualizować jego pozycję sprężyny na podstawie zmiany wprowadzonej w bieżącym widoku danych. Aby zarejestrować detektor, wykonaj te czynności:

  1. Zadzwoń pod numer addUpdateListener() i dołącz detektor do animacji.

    Uwaga: musisz zarejestrować aktualizację detektor przed rozpoczęciem animacji. Detektor aktualizacji powinien jednak rejestrowana tylko wtedy, gdy wymagana jest aktualizacja wartości animacji dla poszczególnych klatek. zmian. Detektor aktualizacji uniemożliwia potencjalnie odtwarzanie animacji w osobnym wątku.

  2. Zastąp onAnimationUpdate() metody powiadamiania wywołującego o zmianie bieżącego obiektu. ten przykładowy kod ilustruje ogólne zastosowanie OnAnimationUpdateListener

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

Detektor zakończenia animacji

OnAnimationEndListener powiadamia o zakończeniu animacji. Możesz skonfigurować detektor, aby odbierał wywołanie zwrotne za każdym razem, gdy animacja osiągnie równowagę lub zostanie anulowana. Do zarejestruj odbiornik, wykonaj te czynności:

  1. Zadzwoń pod numer addEndListener() i dołącz detektor do animacji.
  2. Zastąp onAnimationEnd() metoda odbierania powiadomień za każdym razem, gdy animacja osiągnie równowagę lub zostało anulowane.

Usuń detektory

Aby przestać otrzymywać wywołania zwrotne aktualizacji animacji i zakończenia animacji, zadzwoń do: removeUpdateListener() i removeEndListener() metod weryfikacji danych.

Ustaw wartość początkową animacji

Aby ustawić wartość początkową animacji, wywołaj funkcję setStartValue() i przekazywać wartość początkową animacji. Jeśli nie ustawisz parametru wartość początkowa, animacja używa bieżącej wartości właściwości obiektu jako wartość początkową.

Ustaw zakres wartości animacji

Możesz ustawić minimalne i maksymalne wartości animacji ograniczyć wartość właściwości do określonego zakresu. Pomaga też kontrolować zakresu w przypadku animowania właściwości o wewnętrznym zakresie, jak alfa (od 0 do 1).

  • Aby ustawić minimalną wartość, wywołaj funkcję setMinValue() i przekazywać minimalną wartość właściwości.
  • Aby ustawić maksymalną wartość, wywołaj setMaxValue() i przekazywać maksymalną wartość właściwości.

Obie metody zwracają animację, dla której ustawiana jest wartość.

Uwaga: jeśli ustawisz wartość początkową i będziesz mieć zdefiniowano zakres wartości animacji, upewnij się, że wartość początkowa mieści się w zakresie od wartości minimalnej i maksymalnego zakresu.

Ustaw prędkość początkową

Prędkość początkowa określa szybkość, z jaką zmienia się właściwość animacji początku animacji. Domyślna prędkość początkowa jest ustawiona na zero piks. na sekundę. Możesz ustawić prędkość wczytywania albo lub używanie stałej wartości jako szybkości początkowej. Jeśli wybierzesz mają stałą wartość, zalecamy określenie wartości dp na sekundę oraz a potem przeliczać go na piksele na sekundę. Określanie wartości w dp na sekundę umożliwia zachowanie prędkości niezależnie od gęstości i formatu. Więcej informacji o konwertowaniu wartości na piksele na sekundę znajdziesz w Przeliczanie dp na sekundę na piksele na sekundę .

Aby ustawić prędkość, wywołaj funkcję setStartVelocity() i przekazywać prędkość w pikselach na sekundę. Metoda zwraca wartość obiekt siły na sprężynie, dla którego ustalona jest prędkość.

Uwaga: użyj atrybutu GestureDetector.OnGestureListener lub VelocityTracker metod klas do pobierania i obliczania z prędkością gestów dotykowych.

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

Przeliczanie dp na sekundę na piksele na sekundę

Prędkość sprężyny musi być podana w pikselach na sekundę. Jeśli zdecydujesz się podać stała wartość jako początek prędkości, podaj wartość w dp na sekundę a potem przeliczać go na piksele na sekundę. Do konwersji służy funkcja applyDimension() z klasy TypedValue. Zapoznaj się z ten przykładowy kod:

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 metodę pobierającą i metod ustawiania dla każdej z właściwości sprężyny, takich jak tłumienie proporcje i sztywność. Aby ustawić właściwości sprężyny, musisz wybrać jedną z tych opcji: możesz pobrać obiekt siły sprężyny lub utworzyć niestandardową siłę naprężenia, w której można ustawić właściwości. Więcej informacji o tworzeniu siła sprężyny, odnosi się do Tworzenie niestandardowej siły sprężyny .

Wskazówka: podczas korzystania z metod ustawiania możesz utworzysz łańcuch metod, ponieważ wszystkie metody ustalające zwracają siłę sprężyny obiektu.

Współczynnik tłumienia

Współczynnik tłumienia opisuje stopniowe zmniejszanie oscylacji sprężyny. Według używając współczynnika tłumienia, możesz określić szybkość spadku oscylacji od jednego do kolejnego. Istnieją cztery sposoby nawilżania wiosna:

  • Przeciążenie występuje, gdy współczynnik tłumienia jest większy niż 1. Pozwala obiekt delikatnie powróci do położenia spoczynkowego.
  • Tłumienie krytyczne ma miejsce, gdy współczynnik tłumienia jest równy 1. Pozwala obiekt powraca do położenia spoczynkowego w najkrótszym czasie.
  • Niedostateczne tłumienie występuje, gdy współczynnik tłumienia jest mniejszy niż jeden. Pozwala wielokrotnym przekraczaniem obiektu, przekazując pozycję spoczynku, stopniowo osiąga pozycję spoczynkową.
  • Tłumienie nie jest tłumione, gdy współczynnik tłumienia wynosi 0. Dzięki niemu obiekt oscyluje przez cały czas.

Aby dodać współczynnik tłumienia do sprężyny, wykonaj te czynności:

  1. Zadzwoń pod numer getSpring() do pobrania sprężyny w celu dodania współczynnika tłumienia.
  2. Zadzwoń pod numer setDampingRatio() i przekazać współczynnik tłumienia, jaki chcesz dodać do sprężyny. zwraca obiekt siły sprężyny, dla którego ustawiony jest współczynnik tłumienia.

    Uwaga: współczynnik tłumienia musi wynosić liczba nieujemna. Jeśli ustawisz współczynnik tłumienia na zero, sprężyna nigdy nie osiągają pozycji spoczynkowej. Inaczej mówiąc, zmienia się w nieskończoność.

W systemie dostępne są te stałe współczynnika tłumienia:

Rysunek 2. Wysokie odbicie

Rysunek 3. Średnie odbicie

Rysunek 4. Niski współczynnik odrzuceń

Rysunek 5. Brak odrzuceń

Domyślny współczynnik tłumienia jest ustawiony na 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ść, która służy do pomiaru siły wiosną. Sztywna sprężyna stosuje większą siłę na przyczepiony obiekt gdy sprężyna nie znajduje się w pozycji spoczynku. Aby zwiększyć sztywność sprężyny, wykonaj te czynności:

  1. Zadzwoń pod numer getSpring() do pobrania sprężyny i zwiększenia sztywności.
  2. Zadzwoń pod numer setStiffness() i prześlij wartość sztywności, którą chcesz dodać do sprężyny. zwraca obiekt siły sprężyny, dla którego ustawiono sztywność.

    Uwaga: sztywność musi być liczba dodatnia.

W systemie dostępne są te stałe sztywności:

Rysunek 6. Duża sztywność

Rysunek 7. Średnia sztywność

Rysunek 8. Niska sztywność

Rysunek 9. Bardzo niska sztywność

Domyślna sztywność jest ustawiona na 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);
…

Utwórz niestandardową siłę sprężyny

Zamiast używać domyślnej siły sprężyny możesz utworzyć niestandardową siłę sprężyny. siła sprężyny. Niestandardowa siła sprężyny umożliwia współdzielenie tej samej siły sprężyny w kilku wiosennych animacjach. Po utworzeniu źródła możesz skonfigurować właściwości takie jak współczynnik tłumienia i sztywność.

  1. Utwórz obiekt SpringForce.

    SpringForce force = new SpringForce();

  2. Przypisz właściwości, wywołując je. Możesz też utworzyć łańcuch metod.

    force.setDampingRatio(DAMPING_RATIO_LOW_BOUNCY).setStiffness(STIFFNESS_LOW);

  3. Zadzwoń pod numer setSpring() aby ustawić sprężynę w animacji.

    setSpring(force);

Uruchom animację

Tę animację można rozpocząć na dwa sposoby: wywołując funkcję start() lub wywołując animateToFinalPosition() . Obie metody muszą być wywoływane w wątku głównym.

animateToFinalPosition() wykonuje 2 czynności:

  • Ustawia końcową pozycję sprężyny.
  • Uruchamia animację, jeśli jeszcze się nie rozpoczęła.

Ponieważ metoda aktualizuje końcową pozycję sprężyny i rozpoczyna ruch w razie potrzeby animację, możesz wywołać tę metodę w dowolnym momencie, aby zmienić kurs. animacji. Na przykład w przypadku połączonej łańcuchowo wiosennej animacji zależy od innego. W przypadku takiej animacji lepiej wygodnie jest używać animateToFinalPosition() . Użycie tej metody w połączonej łańcuchowo wiosennej animacji pozwala uniknąć aby się dowiedzieć, czy animacja, którą chcesz zaktualizować w następnej kolejności, jest obecnie aktywna.

Rysunek 10 przedstawia łańcuchową animację sprężyny, w której animacja zależy od innego widoku.

Łańcuch – prezentacja
Rysunek 10. Łańcuch – prezentacja
.

Aby użyć aplikacji animateToFinalPosition() musisz wywołać metodę animateToFinalPosition() i przekazać resztę sprężyny. Możesz też ustawić pozostałe położenie źródła, przez wywołanie funkcji setFinalPosition() .

Metoda start() nie ustawiaj od razu wartości właściwości na wartość początkową. Obiekt wartość zmienia się w momencie każdego pulsu animacji, co następuje przed przejściem pobierania. W rezultacie zmiany są odzwierciedlane w następnej ramce, tak jakby wartości są ustawiane natychmiast.

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();
…

Anuluj animację

Możesz anulować odtwarzanie animacji lub przejść do końca. Sytuacja idealna anulowanie lub przejście do końca amigracji. wymaga natychmiastowego zakończenia animacji. To jest najczęściej, gdy użytkownik nagle wychodzi z aplikacji lub widok staje się niewidoczny.

Animację możesz zakończyć na 2 sposoby. Metoda cancel() kończy animację z wartością, w której się znajduje. Metoda skipToEnd() pomija animację do ostatecznej wartości, a następnie ją zamyka.

Przed zakończeniem animacji sprawdź, stanu źródła. Jeśli stan nie jest wyciszony, animacja nie może dotrzeć w pozycji spoczynku. Aby sprawdzić stan sprężyny, wywołaj funkcję Metoda canSkipToEnd(). Jeśli sprężyna jest tłumiona, metoda zwraca true, w przeciwnym razie funkcja false

Znając stan sprężyny, możesz zakończyć animację, za pomocą skipToEnd() lub Metoda cancel(). cancel() metoda musi być wywoływana tylko w wątku głównym.

Uwaga: najczęściej skipToEnd() przyczyny metody wzrokowy skok.