MotionLayout — это тип макета, который помогает управлять анимацией движения и виджетов в вашем приложении. MotionLayout — это подкласс ConstraintLayout , основанный на его богатых возможностях макетирования. MotionLayout , являющийся частью библиотеки ConstraintLayout , доступен в качестве вспомогательной библиотеки.
MotionLayout устраняет разрыв между переходами макета и сложной обработкой движений, предлагая сочетание функций между инфраструктурой анимации свойств , TransitionManager и CoordinatorLayout .
Помимо описания переходов между макетами, MotionLayout позволяет анимировать любые свойства макета. Более того, он по своей сути поддерживает доступные для поиска переходы . Это означает, что вы можете мгновенно отобразить любую точку перехода в зависимости от какого-либо условия, например сенсорного ввода. MotionLayout также поддерживает ключевые кадры, позволяя полностью настраивать переходы в соответствии с вашими потребностями.
MotionLayout полностью декларативен, что означает, что вы можете описать любые переходы в XML, независимо от их сложности.
Рекомендации по проектированию
MotionLayout предназначен для перемещения, изменения размера и анимации элементов пользовательского интерфейса, с которыми взаимодействуют пользователи, таких как кнопки и строки заголовка. Не используйте движение в своем приложении как ненужный спецэффект. Используйте его, чтобы помочь пользователям понять, что делает ваше приложение. Дополнительные сведения о разработке приложения с использованием движения см. в разделе Material Design «Понимание движения» .
Начать
Выполните следующие действия, чтобы начать использовать MotionLayout в своем проекте.
Добавьте зависимость
ConstraintLayout: чтобы использоватьMotionLayoutв своем проекте, добавьте зависимостьConstraintLayout2.0 в файлbuild.gradleвашего приложения. Если вы используете AndroidX, добавьте следующую зависимость:классный
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.1" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.1" }
Котлин
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.1") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.1") }
Создайте файл
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)
