Przejście niestandardowe umożliwia tworzenie animacji, która nie jest dostępna w żadnej z wbudowanych klas przejść. Możesz na przykład zdefiniować niestandardowe przejście, które powoduje przyciemnienie koloru pierwszego planu tekstu i pol wejściowych, aby wskazać, że pola są wyłączone na nowym ekranie. Dzięki temu użytkownicy będą mogli zobaczyć wyłączone pola.
Przejście niestandardowe, takie jak jeden z wbudowanych typów przejść, stosuje animacje do podrzędnych widoków zarówno początkowej, jak i końcowej sceny. W przeciwieństwie do wbudowanych typów przejść musisz jednak podać kod, który rejestruje wartości właściwości i generuje animacje. Możesz też zdefiniować podzbiór widoków docelowych dla animacji.
Na tej stronie dowiesz się, jak rejestrować wartości właściwości i generować animacje, aby tworzyć niestandardowe przejścia.
Rozszerzenie klasy Transition
Aby utworzyć niestandardowe przejście, dodaj do projektu klasę, która rozszerza klasę Transition
i zastępuje funkcje pokazane w tym fragmencie kodu:
class CustomTransition : Transition() { override fun captureStartValues(transitionValues: TransitionValues) {} override fun captureEndValues(transitionValues: TransitionValues) {} override fun createAnimator( sceneRoot: ViewGroup, startValues: TransitionValues?, endValues: TransitionValues? ): Animator? {} }
public class CustomTransition extends Transition { @Override public void captureStartValues(TransitionValues values) {} @Override public void captureEndValues(TransitionValues values) {} @Override public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) {} }
W poniższych sekcjach znajdziesz informacje o tym, jak zastąpić te funkcje.
Przechwyć wartości właściwości widoku
Animacje przejścia korzystają z systemu animacji właściwości opisanego w artykule Omówienie animacji właściwości. Animacje właściwości zmieniają wartość początkową właściwości widoku na wartość końcową w określonym przedziale czasu, więc framework musi mieć zarówno wartość początkową, jak i końcową właściwości, aby móc utworzyć animację.
Jednak animacja właściwości wymaga zwykle tylko niewielkiej podgrupy wszystkich wartości właściwości widoku. Na przykład animacja koloru wymaga wartości właściwości koloru, a animacja ruchu – wartości właściwości pozycji. Wartości właściwości potrzebne do animacji są specyficzne dla przejścia, dlatego framework nie udostępnia wszystkich wartości właściwości. Zamiast tego wywołuje funkcje wywołania zwrotnego, które umożliwiają przejście do rejestrowania tylko tych wartości właściwości, których potrzebuje framework, i przechowywanie ich w ramach frameworka.
Przechwyć wartości początkowe
Aby przekazać wartości początkowego widoku do frameworku, zastosuj funkcję captureStartValues(transitionValues)
. Framework wywołuje tę funkcję dla każdego widoku w scenie początkowej. Argument funkcji to obiekt TransitionValues
zawierający odwołanie do widoku i wyjątek Map
, w którym można przechowywać wybrane wartości widoku. W swojej implementacji pobieraj te wartości właściwości i przekazuj je z powrotem do frameworku, przechowując je na mapie.
Aby mieć pewność, że klucz wartości właściwości nie koliduje z innymi kluczami TransitionValues
, użyj tego schematu nazewnictwa:
package_name:transition_name:property_name
Ten fragment kodu pokazuje implementację funkcji captureStartValues()
:
class CustomTransition : Transition() { // Define a key for storing a property value in // TransitionValues.values with the syntax // package_name:transition_class:property_name to avoid collisions private val PROPNAME_BACKGROUND = "com.example.android.customtransition:CustomTransition:background" override fun captureStartValues(transitionValues: TransitionValues) { // Call the convenience method captureValues captureValues(transitionValues) } // For the view in transitionValues.view, get the values you // want and put them in transitionValues.values private fun captureValues(transitionValues: TransitionValues) { // Get a reference to the view val view = transitionValues.view // Store its background property in the values map transitionValues.values[PROPNAME_BACKGROUND] = view.background } ... }
public class CustomTransition extends Transition { // Define a key for storing a property value in // TransitionValues.values with the syntax // package_name:transition_class:property_name to avoid collisions private static final String PROPNAME_BACKGROUND = "com.example.android.customtransition:CustomTransition:background"; @Override public void captureStartValues(TransitionValues transitionValues) { // Call the convenience method captureValues captureValues(transitionValues); } // For the view in transitionValues.view, get the values you // want and put them in transitionValues.values private void captureValues(TransitionValues transitionValues) { // Get a reference to the view View view = transitionValues.view; // Store its background property in the values map transitionValues.values.put(PROPNAME_BACKGROUND, view.getBackground()); } ... }
Przechwytywanie wartości końcowych
Framework wywołuje funkcję captureEndValues(TransitionValues)
raz dla każdego docelowego widoku w scenie końcowej. W pozostałych aspektach captureEndValues()
działa tak samo jak captureStartValues()
.
Ten fragment kodu pokazuje implementację funkcji captureEndValues()
:
override fun captureEndValues(transitionValues: TransitionValues) { captureValues(transitionValues) }
@Override public void captureEndValues(TransitionValues transitionValues) { captureValues(transitionValues); }
W tym przykładzie funkcje captureStartValues()
i captureEndValues()
wywołują funkcję captureValues()
, aby pobierać i przechowywać wartości. Właściwość widoku, którą zwraca funkcja captureValues()
, jest taka sama, ale ma różne wartości w scenkach początkowej i końcowej. Framework utrzymuje oddzielne mapy dla stanu początkowego i końcowego widoku.
Tworzenie niestandardowego animatora
Aby animować zmiany widoku między stanem w scenie początkowej a stanem w scenie końcowej, podaj animatora, zastępując funkcję createAnimator()
. Gdy wywołuje tę funkcję, przekazuje widok sceny skojarzonej z obiektem TransitionValues
, który zawiera zarejestrowane wartości początkowe i końcowe.
Liczba wywołań funkcji createAnimator()
przez framework zależy od zmian, które występują między początkową a końcową sceną.
Możesz na przykład zastosować animację znikania lub pojawiania się jako przejście niestandardowe. Jeśli scena początkowa zawiera 5 celów, z których 2 są usunięte ze sceny końcowej, a scena końcowa zawiera 3 cele ze sceny początkowej oraz nowy cel, framework wywołuje funkcję createAnimator()
6 razy.
Trzy z tych wywołań animują zniknięcie i pojawianie się obiektów docelowych, które pozostają w obu scenach. Kolejne 2 wywołania animują znikanie celów usuniętych ze sceny końcowej. Jedna z nich animuje stopniowe pojawianie się nowego celu w scenie końcowej.
W przypadku widoków docelowych, które występują zarówno w scenie początkowej, jak i końcowej, framework udostępnia obiekt TransitionValues
zarówno dla argumentów startValues
, jak i endValues
. W przypadku widoków docelowych, które występują tylko w początkowej lub końcowej scenie, framework udostępnia obiekt TransitionValues
dla odpowiedniego argumentu i null
dla drugiego.
Aby zastosować funkcję createAnimator(ViewGroup, TransitionValues, TransitionValues)
podczas tworzenia przejścia niestandardowego, użyj zarejestrowanych wartości właściwości widoku, aby utworzyć obiekt Animator
i zwrócić go do frameworku. Przykładową implementację znajdziesz w klasie ChangeColor
w przykładzie
CustomTransition. Więcej informacji o animacji właściwości znajdziesz w artykule Animacja właściwości.
Stosowanie przejścia niestandardowego
Niestandardowe przejścia działają tak samo jak wbudowane przejścia. Możesz zastosować niestandardową zmianę za pomocą menedżera zmian zgodnie z opisem w artykule Stosowanie przejścia.