MotionLayout to typ układu, który pomaga zarządzać ruchem i animacją widżetów w aplikacji.MotionLayout to podklasa ConstraintLayout, która wykorzystuje jej rozbudowane możliwości układu. W ramach biblioteki ConstraintLayout dostępna jest biblioteka pomocy MotionLayout.
MotionLayout wypełnia lukę między przejściami układu a obsługą złożonego ruchu, oferując połączenie funkcji platformy animacji właściwości, TransitionManager i CoordinatorLayout.
Oprócz opisywania przejść między układami MotionLayout umożliwia animowanie dowolnych właściwości układu. Ponadto obsługuje on przejścia, które można przewijać. Oznacza to, że możesz natychmiast wyświetlić dowolny punkt w przejściu na podstawie określonego warunku, np. dotknięcia. MotionLayout obsługuje też klatki kluczowe, co umożliwia w pełni dostosowane przejścia do Twoich potrzeb.
MotionLayout jest w pełni deklaratywny, co oznacza, że możesz opisać w XML dowolne przejścia, niezależnie od ich złożoności.
Uwagi dotyczące projektu
MotionLayout służy do przesuwania, zmiany rozmiaru i animowania elementów interfejsu, z którymi użytkownicy wchodzą w interakcję, takich jak przyciski i paski tytułu. Nie używaj ruchu w aplikacji jako niepotrzebnego efektu specjalnego. Używaj go, aby pomóc użytkownikom zrozumieć, co robi Twoja aplikacja. Więcej informacji o projektowaniu aplikacji z animacjami znajdziesz w sekcji Understanding motion (Zrozumienie animacji) w Material Design.
Rozpocznij
Aby zacząć korzystać z MotionLayout w projekcie, wykonaj te czynności.
-
Dodaj zależność
ConstraintLayout: aby używaćMotionLayoutw projekcie, dodaj zależnośćConstraintLayout2.0 do plikubuild.gradleaplikacji. Jeśli używasz AndroidX, dodaj następującą zależność:Odlotowe
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.1" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.1" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.1") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.1") }
-
Utwórz plik
MotionLayout:MotionLayoutjest podklasąConstraintLayout, więc możesz przekształcić dowolny istniejący elementConstraintLayoutwMotionLayout, zastępując nazwę klasy w pliku zasobu układu, jak pokazano w tych przykładach:AndroidX
<!-- before: ConstraintLayout --> <androidx.constraintlayout.widget.ConstraintLayout .../> <!-- after: MotionLayout --> <androidx.constraintlayout.motion.widget.MotionLayout .../>
Biblioteka pomocy
<!-- before: ConstraintLayout --> <android.support.constraint.ConstraintLayout .../> <!-- after: MotionLayout --> <android.support.constraint.motion.MotionLayout .../>
Oto pełny przykład pliku
MotionLayout, który określa układ widoczny na ilustracji 1:AndroidX
<?xml version="1.0" encoding="utf-8"?> <!-- activity_main.xml --> <androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/motionLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/scene_01" tools:showPaths="true"> <View android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:background="@color/colorAccent" android:text="Button" /> </androidx.constraintlayout.motion.widget.MotionLayout>
Biblioteka pomocy
<?xml version="1.0" encoding="utf-8"?> <!-- activity_main.xml --> <android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/motionLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/scene_01" tools:showPaths="true"> <View android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:background="@color/colorAccent" android:text="Button" /> </android.support.constraint.motion.MotionLayout>
-
Utwórz MotionScene: w poprzednim przykładzie
MotionLayoutatrybutapp:layoutDescriptionodwołuje się do sceny ruchu. Scena ruchu to plik zasobu XML. W elemencie głównym<MotionScene>scena ruchu zawiera wszystkie opisy ruchu dla odpowiedniego układu. Aby oddzielić informacje o układzie od opisów ruchu, każdy elementMotionLayoutodnosi się do osobnej sceny ruchu. Definicje w scenie ruchu mają pierwszeństwo przed podobnymi definicjami wMotionLayout.Oto przykładowy plik sceny ruchu, który opisuje podstawowy ruch poziomy na rysunku 1:
<?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000"> <OnSwipe motion:touchAnchorId="@+id/button" motion:touchAnchorSide="right" motion:dragDirection="dragRight" /> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
Uwaga:
-
<Transition>zawiera podstawową definicję ruchu.-
motion:constraintSetStartimotion:constraintSetEndto odniesienia do punktów końcowych ruchu. Te punkty końcowe są zdefiniowane w elementach<ConstraintSet>w dalszej części sceny ruchu. -
motion:durationokreśla liczbę milisekund potrzebnych do zakończenia ruchu.
-
-
<OnSwipe>umożliwia tworzenie sterowania dotykowego ruchem.-
motion:touchAnchorId– widok, który użytkownik może przesuwać. -
motion:touchAnchorSideoznacza, że widok jest przeciągany z prawej strony. -
motion:dragDirectionodnosi się do kierunku postępu przeciągania. Na przykładmotion:dragDirection="dragRight"oznacza, że postęp wzrasta, gdy widok jest przeciągany w prawo.
-
-
<ConstraintSet>to miejsce, w którym określasz różne ograniczenia opisujące ruch. W tym przykładzie dla każdego punktu końcowego ruchu zdefiniowano 1<ConstraintSet>. Te punkty końcowe są wyśrodkowane pionowo za pomocą funkcjiapp:layout_constraintTop_toTopOf="parent"iapp:layout_constraintBottom_toBottomOf="parent". W poziomie punkty końcowe znajdują się po lewej i prawej stronie ekranu.
Szczegółowe informacje o różnych elementach obsługiwanych przez scenę ruchu znajdziesz w przykładach MotionLayout.
-
Interpolowane atrybuty
W pliku sceny ruchu elementy ConstraintSet mogą zawierać dodatkowe atrybuty, które są interpolowane podczas przejścia. Oprócz pozycji i obszaru MotionLayout interpoluje te atrybuty:
alphavisibilityelevationrotation,rotationX,rotationYtranslationX,translationY,translationZscaleX,scaleY
Atrybuty niestandardowe
W elemencie <Constraint> możesz użyć elementu <CustomAttribute>, aby określić przejście dla atrybutów, które nie są powiązane z pozycją lub atrybutami View.
<Constraint android:id="@+id/button" ...> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60"/> </Constraint>
Element <CustomAttribute> ma 2 atrybuty:
- Wymagany jest parametr
motion:attributeName, który musi być zgodny z obiektem z metodami pobierania i ustawiania. Funkcje pobierające i ustawiające muszą pasować do określonego wzorca. Na przykładbackgroundColorjest obsługiwane, ponieważ widok ma metody bazowegetBackgroundColor()isetBackgroundColor(). - Inny atrybut, który musisz podać, zależy od typu wartości. Wybierz jeden z tych obsługiwanych typów:
motion:customColorValuekolorówmotion:customIntegerValuedla liczb całkowitychmotion:customFloatValuew przypadku liczb zmiennoprzecinkowych,motion:customStringValuew przypadku ciągów znaków,motion:customDimensionw przypadku wymiarówmotion:customBooleanw przypadku wartości logicznych
Podczas określania atrybutu niestandardowego zdefiniuj wartości punktu końcowego w elementach <ConstraintSet> i <ConstraintSet>.
Zmiana koloru tła
W nawiązaniu do poprzedniego przykładu załóżmy, że chcesz, aby kolory widoku zmieniały się w ramach jego ruchu, jak pokazano na rysunku 2.
Dodaj element <CustomAttribute> do każdego elementu ConstraintSet, jak pokazano w tym fragmencie kodu:
<ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#9999FF" /> </Constraint> </ConstraintSet>
Dodatkowe atrybuty MotionLayout
Oprócz atrybutów z poprzedniego przykładu MotionLayout ma inne atrybuty, które możesz określić:
app:applyMotionScene="boolean"wskazuje, czy zastosować scenę ruchu. Domyślna wartość tego atrybutu totrue.app:showPaths="boolean"określa, czy ścieżki ruchu mają być wyświetlane podczas ruchu. Domyślna wartość tego atrybutu tofalse.app:progress="float"umożliwia wyraźne określenie postępu przejścia. Możesz użyć dowolnej wartości zmiennoprzecinkowej z zakresu od0(początek przejścia) do1(koniec przejścia).app:currentState="reference"umożliwia określenie konkretnegoConstraintSet.app:motionDebugumożliwia wyświetlanie dodatkowych informacji na potrzeby debugowania dotyczących ruchu. Możliwe wartości to"SHOW_PROGRESS","SHOW_PATH"lub"SHOW_ALL".
Dodatkowe materiały
Więcej informacji o MotionLayout znajdziesz w tych materiałach:
- Zaawansowany Android w środowisku Kotlin 03.2: animacja z MotionLayout
- Przykłady MotionLayout
- Przykłady MotionLayout/ConstraintLayout w GitHubie
- Wprowadzenie do MotionLayout (część I)
- Wprowadzenie do MotionLayout (część II)
- Wprowadzenie do MotionLayout (część III)
- Wprowadzenie do MotionLayout (część IV)