MotionLayout
— это тип макета, который помогает вам управлять анимацией движения и виджетов в вашем приложении. MotionLayout
— это подкласс ConstraintLayout
, основанный на его богатых возможностях макетирования. MotionLayout
, являющийся частью библиотеки ConstraintLayout
, доступен в качестве вспомогательной библиотеки.
MotionLayout
устраняет разрыв между переходами макета и сложной обработкой движений, предлагая сочетание функций между инфраструктурой анимации свойств , TransitionManager
и CoordinatorLayout
.
Помимо описания переходов между макетами, MotionLayout
позволяет анимировать любые свойства макета. Более того, он по своей сути поддерживает доступные для поиска переходы . Это означает, что вы можете мгновенно отобразить любую точку перехода в зависимости от какого-либо условия, например сенсорного ввода. MotionLayout
также поддерживает ключевые кадры, позволяя полностью настраивать переходы в соответствии с вашими потребностями.
MotionLayout
полностью декларативен, что означает, что вы можете описать любые переходы в XML, независимо от их сложности.
Рекомендации по проектированию
MotionLayout
предназначен для перемещения, изменения размера и анимации элементов пользовательского интерфейса, с которыми взаимодействуют пользователи, таких как кнопки и строки заголовка. Не используйте движение в своем приложении как ненужный спецэффект. Используйте его, чтобы помочь пользователям понять, что делает ваше приложение. Дополнительные сведения о разработке приложения с использованием движения см. в разделе Material Design «Понимание движения» .
Начать
Выполните следующие действия, чтобы начать использовать MotionLayout
в своем проекте.
Добавьте зависимость
ConstraintLayout
: чтобы использоватьMotionLayout
в своем проекте, добавьте зависимостьConstraintLayout
2.0 в файлbuild.gradle
вашего приложения. Если вы используете AndroidX, добавьте следующую зависимость:Groovy
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") }
Создайте файл
MotionLayout
:MotionLayout
— это подклассConstraintLayout
, поэтому вы можете преобразовать любой существующийConstraintLayout
вMotionLayout
, заменив имя класса в файле ресурсов макета, как показано в следующих примерах:AndroidX
<!-- before: ConstraintLayout --> <androidx.constraintlayout.widget.ConstraintLayout .../> <!-- after: MotionLayout --> <androidx.constraintlayout.motion.widget.MotionLayout .../>
Поддержка библиотеки
<!-- before: ConstraintLayout --> <android.support.constraint.ConstraintLayout .../> <!-- after: MotionLayout --> <android.support.constraint.motion.MotionLayout .../>
Вот полный пример файла
MotionLayout
, который определяет макет, показанный на рисунке 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>
Поддержка библиотеки
<?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>
Создайте MotionScene: в предыдущем примере
MotionLayout
атрибутapp:layoutDescription
ссылается на сцену движения . Сцена движения — это файл ресурсов XML. В корневом элементе<MotionScene>
сцена движения содержит все описания движения для соответствующего макета. Чтобы хранить информацию о макете отдельно от описаний движения, каждыйMotionLayout
ссылается на отдельную сцену движения. Определения в сцене движения имеют приоритет над любыми аналогичными определениями вMotionLayout
.Вот пример файла сцены движения, который описывает базовое горизонтальное движение на рисунке 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>
Обратите внимание на следующее:
<Transition>
содержит базовое определение движения.motion:constraintSetStart
иmotion:constraintSetEnd
— это ссылки на конечные точки движения. Эти конечные точки определяются в элементах<ConstraintSet>
позже в сцене движения.motion:duration
указывает количество миллисекунд, необходимое для завершения движения.
<OnSwipe>
позволяет создать сенсорное управление движением.motion:touchAnchorId
относится к представлению, которое пользователь может провести и перетащить.motion:touchAnchorSide
означает, что представление перетаскивается с правой стороны.motion:dragDirection
относится к направлению перетаскивания . Например,motion:dragDirection="dragRight"
означает, что прогресс увеличивается при перетаскивании представления вправо.
<ConstraintSet>
— здесь вы определяете различные ограничения, описывающие ваше движение. В этом примере один<ConstraintSet>
определен для каждой конечной точки вашего движения. Эти конечные точки центрируются по вертикали с помощьюapp:layout_constraintTop_toTopOf="parent"
иapp:layout_constraintBottom_toBottomOf="parent"
. По горизонтали конечные точки находятся в крайней левой и правой частях экрана.
Более подробное описание различных элементов, поддерживаемых движущейся сценой, см. в примерах MotionLayout .
Интерполированные атрибуты
В файле сцены движения элементы ConstraintSet
могут содержать дополнительные атрибуты, которые интерполируются во время перехода. Помимо позиции и границ, MotionLayout
интерполирует следующие атрибуты:
-
alpha
-
visibility
-
elevation
-
rotation
,rotationX
,rotationY
-
translationX
,translationY
,translationZ
-
scaleX
,scaleY
Пользовательские атрибуты
Внутри <Constraint>
вы можете использовать элемент <CustomAttribute>
, чтобы указать переход для атрибутов, которые не просто связаны с атрибутами положения или View
.
<Constraint android:id="@+id/button" ...> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60"/> </Constraint>
<CustomAttribute>
содержит два собственных атрибута:
-
motion:attributeName
является обязательным и должен соответствовать объекту с помощью методов получения и установки. Геттер и сеттер должны соответствовать определенному шаблону. Например, поддерживаетсяbackgroundColor
, поскольку представление имеет базовые методыgetBackgroundColor()
иsetBackgroundColor()
. - Другой атрибут, который вы должны предоставить, основан на типе значения. Выберите один из следующих поддерживаемых типов:
-
motion:customColorValue
для цветов -
motion:customIntegerValue
для целых чисел -
motion:customFloatValue
для поплавков -
motion:customStringValue
для строк -
motion:customDimension
для размеров -
motion:customBoolean
для логических значений
-
При указании настраиваемого атрибута определите значения конечной точки как в начальном, так и в конечном элементах <ConstraintSet>
.
Изменить цвет фона
Опираясь на предыдущий пример, предположим, что вы хотите, чтобы цвета представления менялись при его движении, как показано на рисунке 2.
Добавьте элемент <CustomAttribute>
к каждому элементу ConstraintSet
, как показано в следующем фрагменте кода:
<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>
Дополнительные атрибуты MotionLayout
Помимо атрибутов из предыдущего примера, MotionLayout
имеет и другие атрибуты, которые вы, возможно, захотите указать:
-
app:applyMotionScene="boolean"
указывает, следует ли применять сцену движения. Значение по умолчанию для этого атрибута —true
. -
app:showPaths="boolean"
указывает, следует ли отображать пути движения во время его выполнения. Значение по умолчанию для этого атрибута —false
. -
app:progress="float"
позволяет явно указать ход перехода. Вы можете использовать любое значение с плавающей запятой от0
(начало перехода) до1
(конец перехода). -
app:currentState="reference"
позволяет указать конкретныйConstraintSet
. -
app:motionDebug
позволяет отображать дополнительную отладочную информацию о движении. Возможные значения:"SHOW_PROGRESS"
,"SHOW_PATH"
или"SHOW_ALL"
.
Дополнительные ресурсы
Дополнительные сведения о MotionLayout
см. в следующих ресурсах:
- Продвинутый Android в Kotlin 03.2: анимация с помощью MotionLayout
- Примеры моушн-лейаута
- Примеры MotionLayout/ConstraintLayout на GitHub
- Введение в MotionLayout (часть I)
- Введение в MotionLayout (часть II)
- Введение в MotionLayout (часть III)
- Введение в MotionLayout (часть IV)