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 rozbudowane możliwości układu. W ramach biblioteki ConstraintLayout
MotionLayout
jest dostępny jako biblioteka pomocy.
MotionLayout
wypełnia lukę między przejściami układu a złożoną obsługą ruchu, oferując połączenie różnych funkcji między strukturą animacji właściwości, TransitionManager
i CoordinatorLayout
.
Oprócz opisu przejść między układami, MotionLayout
umożliwia animowanie dowolnych właściwości układu. Co więcej, z założenia obsługuje przejściowe przejścia. Oznacza to, że możesz od razu pokazać dowolny punkt przejścia pod pewnymi warunkami, np. za pomocą dotyku. MotionLayout
obsługuje też klatki kluczowe, dzięki czemu możesz w pełni dostosować przejścia do Twoich potrzeb.
Parametr MotionLayout
jest w pełni deklaracyjny, co oznacza, że w pliku XML możesz opisywać dowolne przejścia, nawet te bardzo złożone.
Uwagi dotyczące projektu
MotionLayout
służy do przesuwania i animowania elementów interfejsu, z którymi użytkownicy wchodzą w interakcje, takich jak przyciski i paski tytułu, oraz zmienianie ich rozmiaru. Nie używaj ruchu w aplikacji
jako nieuzasadnionego efektu specjalnego. Używaj jej, aby pokazać użytkownikom,
jak działa Twoja aplikacja. Więcej informacji na temat projektowania aplikacji z ruchem znajdziesz w sekcji Material Design Interpretowanie ruchu.
Rozpocznij
Aby zacząć używać usługi MotionLayout
w swoim projekcie, wykonaj te czynności.
-
Dodaj zależność
ConstraintLayout
: aby używać w projekcieMotionLayout
, dodaj zależnośćConstraintLayout
2.0 do plikubuild.gradle
aplikacji. Jeśli używasz AndroidaX, dodaj tę zależność:Odlotowy
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha13" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha13") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13") }
-
Utwórz plik
MotionLayout
:MotionLayout
to podklasa klasyConstraintLayout
, więc możesz przekształcić dowolny istniejący obiektConstraintLayout
wMotionLayout
, zastępując nazwę klasy w pliku zasobów układu, jak 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 pokazany na Rysunku 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
MotionLayout
atrybutapp:layoutDescription
odwołuje się do sceny ruchu. Scena ruchu to plik zasobów XML. W elemencie głównym<MotionScene>
scena ruchu zawiera wszystkie opisy ruchu dla danego układu. Aby oddzielić informacje o układzie od opisów ruchu, każdy elementMotionLayout
odwołuje się do innej sceny ruchu. Definicje zawarte w scenie ruchu mają pierwszeństwo przed podobnymi definicjami zMotionLayout
.Oto przykładowy plik sceny ruchu opisujący podstawowy ruch w poziomie na ilustracji 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:constraintSetStart
imotion:constraintSetEnd
to odwołania do punktów końcowych ruchu. Te punkty końcowe są zdefiniowane w elementach<ConstraintSet>
na późniejszym etapie sceny ruchu. -
motion:duration
określa czas w milisekundach, po jakim następuje ruch.
-
-
<OnSwipe>
umożliwia skonfigurowanie sterowania dotykowego ruchu.-
motion:touchAnchorId
odnosi się do widoku, który użytkownik może przesuwać i przeciągać. -
motion:touchAnchorSide
oznacza, że widok jest przeciągany z prawej strony. -
motion:dragDirection
odnosi się do kierunku postępu przeciągania. Na przykładmotion:dragDirection="dragRight"
oznacza, że postęp rośnie w miarę przeciągania widoku w prawo.
-
-
<ConstraintSet>
to miejsce, w którym definiujesz różne ograniczenia opisujące Twój ruch. W tym przykładzie każdy punkt końcowy ruchu ma jeden<ConstraintSet>
. Te punkty końcowe są wyśrodkowane w pionie za pomocą właściwościapp:layout_constraintTop_toTopOf="parent"
iapp:layout_constraintBottom_toBottomOf="parent"
. W poziomie znajdują się punkty końcowe po lewej i prawej stronie ekranu.
Aby dowiedzieć się więcej o różnych elementach obsługiwanych przez scenę ruchu, zapoznaj się z przykładami Motion Layout.
-
Interpolowane atrybuty
Elementy ConstraintSet
w pliku sceny ruchu mogą zawierać dodatkowe atrybuty, które są interpolowane podczas przejść. Oprócz pozycji i granic te atrybuty są interpolowane przez MotionLayout
:
alpha
visibility
elevation
rotation
,rotationX
,rotationY
translationX
,translationY
,translationZ
scaleX
,scaleY
Atrybuty niestandardowe
W obiekcie <Constraint>
możesz użyć elementu <CustomAttribute>
, aby określić przejście atrybutów, które nie są tylko związane z pozycją czy atrybutami View
.
<Constraint android:id="@+id/button" ...> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60"/> </Constraint>
Element <CustomAttribute>
zawiera 2 własne atrybuty:
- Metoda
motion:attributeName
jest wymagana i musi pasować do obiektu za pomocą metod pobierania i setera. Metody pobierające i ustawiające muszą pasować do konkretnego wzorca. Obsługiwany jest na przykładbackgroundColor
, ponieważ widok zawiera metodygetBackgroundColor()
isetBackgroundColor()
. - Kolejny atrybut, który musisz podać, zależy od typu wartości. Wybierz jeden z tych obsługiwanych typów:
motion:customColorValue
– kolorymotion:customIntegerValue
– liczby całkowitemotion:customFloatValue
dla liczby zmiennoprzecinkowejmotion:customStringValue
dla ciągów tekstowychmotion:customDimension
– wymiarymotion:customBoolean
– wartości logiczne
Określając atrybut niestandardowy, określ wartości punktów końcowych zarówno w elemencie początkowym, jak i końcowym <ConstraintSet>
.
Zmiana koloru tła
Opierając się na poprzednim przykładzie, załóżmy, że kolory widoku zmieniają się wraz z ruchem, tak jak to widać na rys. 2.
Dodaj element <CustomAttribute>
do każdego elementu ConstraintSet
w sposób podany 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 Motion Layout
Oprócz atrybutów z poprzedniego przykładu atrybut MotionLayout
ma też inne atrybuty, które możesz określić:
app:applyMotionScene="boolean"
wskazuje, czy zastosować daną scenę ruchu. Wartość domyślna tego atrybutu totrue
.app:showPaths="boolean"
wskazuje, czy pokazywać ścieżki animacji w trakcie ruchu. Wartość domyślna tego atrybutu tofalse
.app:progress="float"
umożliwia jawne określanie postępu przenoszenia. Możesz użyć dowolnej wartości zmiennoprzecinkowej od0
(początek przejścia) do1
(koniec przejścia).app:currentState="reference"
umożliwia określenie konkretnego elementuConstraintSet
.app:motionDebug
pozwala wyświetlić dodatkowe informacje na temat debugowania ruchu. Możliwe wartości to"SHOW_PROGRESS"
,"SHOW_PATH"
oraz"SHOW_ALL"
.
Dodatkowe materiały
Więcej informacji o MotionLayout
znajdziesz w tych materiałach:
- Zaawansowane funkcje Androida w aplikacji Kotlin 03.2: animacje z użyciem Motion Layout
- Przykłady Motion Layout
- Przykłady Motion Layout/Constraint Sample w serwisie GitHub
- Wprowadzenie do Motion Układ (część I)
- Wprowadzenie do Motion Układ (część II)
- Wprowadzenie do Motion Układ (część III)
- Wprowadzenie do Motion Layout (część IV)