MotionLayout – это тип макета, который помогает управлять движением и анимацией виджетов в приложении. MotionLayout является подклассом ConstraintLayout и основан на его широких возможностях макета. MotionLayout входит в библиотеку ConstraintLayout и доступна как библиотека поддержки.
MotionLayout заполняет пробел между переходами макета и сложной обработкой движения, предлагая сочетание функций между фреймворком анимации свойств, TransitionManager и CoordinatorLayout.
Помимо описания переходов между макетами, MotionLayout позволяет анимировать любые свойства макета. Кроме того, он поддерживает переходы с возможностью перемотки. Это означает, что вы можете мгновенно показать любую точку перехода на основе какого-либо условия, например сенсорного ввода. MotionLayout также поддерживает ключевые кадры, что позволяет полностью настраивать переходы в соответствии с вашими потребностями.
MotionLayout полностью декларативен, то есть вы можете описать любые переходы в XML, независимо от их сложности.
Рекомендации по дизайну
MotionLayout предназначена для перемещения, изменения размера и анимации элементов интерфейса, с которыми взаимодействуют пользователи, например кнопок и строк заголовка. Не используйте движение в приложении в качестве бесплатного спецэффекта. Это поможет пользователям понять, что делает ваше приложение. Дополнительную информацию о разработке приложений с анимацией можно найти в разделе Understanding motion (Общие сведения об анимации) руководства по Material Design.
Начать
Чтобы начать использовать MotionLayout в своем проекте, выполните следующие действия:
-
Добавьте зависимость
ConstraintLayout. Чтобы использоватьMotionLayoutв проекте, добавьте зависимостьConstraintLayout2.0 в файлbuild.gradleприложения. Если вы используете AndroidX, добавьте следующую зависимость:классный
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.2" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.2" }
Котлин
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.2") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.2") }
-
Создайте файл
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ссылается на motion scene. Сцена движения – это 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 интерполирует следующие атрибуты:
alphavisibilityelevationrotation,rotationX,rotationYtranslationX,translationY,translationZscaleX,scaleY
Настраиваемые атрибуты
Внутри <Constraint> можно использовать элемент <CustomAttribute>, чтобы указать переход для атрибутов, которые не связаны с позицией или атрибутами View.
<Constraint android:id="@+id/button" ...> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60"/> </Constraint>
У элемента <CustomAttribute> есть два собственных атрибута:
motion:attributeNameявляется обязательным и должен соответствовать объекту с методами getter и setter. Геттер и сеттер должны соответствовать определенному шаблону. Например, поддерживается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
- Примеры MotionLayout/ConstraintLayout на GitHub
- Введение в MotionLayout (часть I)
- Введение в MotionLayout (часть II)
- Введение в MotionLayout (часть III)
- Введение в MotionLayout (часть IV)