MotionLayout
to typ układu, który ułatwia zarządzanie ruchem i animacją widżetów w aplikacji. MotionLayout
to podklasa klasy ConstraintLayout
, która wykorzystuje zaawansowane możliwości układu. W ramach biblioteki ConstraintLayout
biblioteka MotionLayout
jest dostępna jako biblioteka pomocy.
MotionLayout
wypełnia lukę między przejściami układu i złożoną obsługą ruchu, oferując połączenie platformy animacji właściwości, TransitionManager
i CoordinatorLayout
.
Oprócz opisywania przejść między układami MotionLayout
umożliwia animację dowolnych właściwości układu. Ponadto obsługuje przewijanie przejść. Oznacza to, że możesz od razu pokazać dowolny punkt przejścia w zależności od pewnych warunków, np. dotyku. MotionLayout
obsługuje też klatki kluczowe, co umożliwia pełne dostosowanie przejść do swoich potrzeb.
MotionLayout
jest w pełni deklaratywny, co oznacza, że możesz opisywać wszystkie przejścia w XML, niezależnie od ich złożoności.
Uwagi dotyczące projektu
MotionLayout
służy do przemieszczania, zmiany rozmiaru i animowania elementów interfejsu, z którymi użytkownicy mogą wchodzić w interakcje, takich jak przyciski i paski tytułowe. Nie używaj w aplikacji ruchu jako nieuzasadnionego efektu specjalnego. Użyj go, aby pomóc użytkownikom zrozumieć, co robi Twoja aplikacja. Więcej informacji o projektowaniu aplikacji z użyciem animacji znajdziesz w sekcji Poznawanie animacji w artykule o projektowaniu Material Design.
Rozpocznij
Aby zacząć używać MotionLayout
w projekcie, wykonaj te czynności.
-
Dodaj zależność
ConstraintLayout
: aby używaćMotionLayout
w projekcie, dodaj zależnośćConstraintLayout
2.0 do plikubuild.gradle
aplikacji. Jeśli używasz AndroidX, dodaj te zależności:Odlotowe
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.0-beta01" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-beta01" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.0-beta01") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-beta01") }
-
Utwórz plik
MotionLayout
:MotionLayout
jest podklasąConstraintLayout
, więc możesz przekształcić dowolny istniejący elementConstraintLayout
w elementMotionLayout
, 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 definiuje 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 scenę animacji: w poprzednim przykładzie
MotionLayout
atrybutapp:layoutDescription
odwołuje się do sceny animacji. Scena animacji to plik zasobu XML. Scena ruchu w swoim elemencie głównym<MotionScene>
zawiera wszystkie opisy ruchu dla odpowiedniego układu. Aby oddzielić informacje o układzie od opisów animacji, każdy elementMotionLayout
odwołuje się do osobnej sceny animacji. Definicje w scenie ruchu mają pierwszeństwo przed podobnymi definicjami w sekcjiMotionLayout
.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ę pozwu.-
motion:constraintSetStart
imotion:constraintSetEnd
to odniesienia do punktów końcowych ruchu. Te punkty końcowe są określone w elementach<ConstraintSet>
w dalszej części sceny ruchu. -
motion:duration
określa czas (w milisekundach) potrzebny do ukończenia ruchu.
-
-
<OnSwipe>
umożliwia utworzenie sterowania dotykowego dla ruchu.-
motion:touchAnchorId
– widok, który użytkownik może przesuwać i przeciągać. -
motion:touchAnchorSide
oznacza, że widok jest przeciągany od prawej strony. -
motion:dragDirection
oznacza kierunek postępu przeciągania. Na przykład:motion:dragDirection="dragRight"
oznacza, że postęp zwiększa się, gdy widok jest przeciągany w prawo.
-
-
<ConstraintSet>
to miejsce, w którym definiujesz różne ograniczenia opisujące ruch. W tym przykładzie dla każdego punktu końcowego animacji zdefiniowano<ConstraintSet>
. Te punkty końcowe są wyrównane pionowo za pomocą znacznikówapp:layout_constraintTop_toTopOf="parent"
iapp:layout_constraintBottom_toBottomOf="parent"
. W poziomie punkty końcowe znajdują się po lewej i prawej stronie ekranu.
Więcej informacji o różnych elementach obsługiwanych przez scenę Motion znajdziesz w artykule Przykłady MotionLayout.
-
Atrybuty interpolowane
W pliku sceny animacji elementy ConstraintSet
mogą zawierać dodatkowe atrybuty, które są interpolowane podczas przejścia. Oprócz pozycji i zakresów te atrybuty są interpolowane za pomocą wartości MotionLayout
:
alpha
visibility
elevation
rotation
,rotationX
,rotationY
translationX
,translationY
,translationZ
scaleX
,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 tylko z pozycją lub atrybutami View
.
<Constraint android:id="@+id/button" ...> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60"/> </Constraint>
Element <CustomAttribute>
zawiera 2 atrybuty:
motion:attributeName
jest wymagany i musi być zgodny z obiektem z metodami getter i setter. Metody getter i setter muszą być zgodne z określonym wzorcem. Obsługiwany jest na przykładbackgroundColor
, ponieważ widok danych zawiera metodygetBackgroundColor()
isetBackgroundColor()
.- Inny atrybut, który musisz podać, zależy od typu wartości. Wybierz jeden z obsługiwanych typów:
motion:customColorValue
dla kolorówmotion:customIntegerValue
dla liczb całkowitychmotion:customFloatValue
dla pływakówmotion:customStringValue
– ciągimotion:customDimension
w przypadku wymiarówmotion:customBoolean
w przypadku wartości logicznych
Określając atrybut niestandardowy, określ wartości punktów końcowych zarówno w początkowym, jak i końcowym elemencie <ConstraintSet>
.
Zmiana koloru tła
Kontynuując poprzedni przykład, załóżmy, że chcesz zmieniać kolory widoku w ramach jego ruchu, jak widać 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 też inne atrybuty, które możesz określić:
app:applyMotionScene="boolean"
wskazuje, czy chcesz zastosować scenę ruchu. Domyślna wartość tego atrybutu totrue
.app:showPaths="boolean"
wskazuje, czy ścieżki ruchu mają być wyświetlane podczas odtwarzania ruchu. Domyślna wartość tego atrybutu tofalse
.app:progress="float"
umożliwia określenie postępu przejścia. Możesz użyć dowolnej wartości zmiennoprzecinkowej z zakresu0
(początek przejścia) do1
(koniec przejścia).app:currentState="reference"
umożliwia określenie konkretnegoConstraintSet
.app:motionDebug
pozwala wyświetlić dodatkowe informacje na potrzeby debugowania dotyczącego animacji. Możliwe wartości to"SHOW_PROGRESS"
,"SHOW_PATH"
i"SHOW_ALL"
.
Dodatkowe materiały
Więcej informacji o funkcji MotionLayout
znajdziesz w tych materiałach:
- Zaawansowany Android w Kotlin 03.2: animacja w 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)