Как добавить интерактивную анимацию в приложение с помощью MotionLayout
Несколько удачно размещенных анимаций могут сделать ваше приложение более динамичным и увлекательным, независимо от того, дает ли оно пользователям что-то, на что можно смотреть, пока вы выполняете работу в фоновом режиме, тонко выделяя часть вашего пользовательского интерфейса, с которой пользователям нужно взаимодействовать дальше, или просто добавляя расцветка экрана, которая в противном случае казалась бы плоской и скучной.
В этой статье мы рассмотрим MotionLayout, новый класс, который упрощает добавление сложных интерактивных анимаций в ваши приложения для Android. К концу этого руководства вы будете использовать MotionLayout для создания виджета, который при нажатии анимирует экран, вращает, изменяет размер, меняет цвет и реагирует на события ввода пользователя.
Что такое MotionLayout?
Платформа Android уже предоставляет несколько решений для добавления анимации в ваши приложения, например TransitionManager и Animated Vector Drawables. Однако с этими решениями может быть сложно работать, а некоторые из них имеют ограничения, которые могут помешать вам реализовать свои анимации в точности так, как вы их себе представляли.
MotionLayout – это новый класс, предназначенный для преодоления разрыва между переходами макета и сложной обработкой движения. Подобно TransitionManager, MotionLayout позволяет описывать переход между двумя макетами. В отличие от TransitionManager, MotionLayout не ограничивается атрибутами макета, поэтому у вас больше гибкости для создания настраиваемых уникальных анимаций.
По своей сути MotionLayout позволяет перемещать виджет из точки A в точку B с дополнительными отклонениями и эффектами между ними. Например, вы можете использовать MotionLayout для перемещения ImageView из нижней части экрана в верхнюю часть экрана, увеличивая размер изображения на 50 процентов. В этом руководстве мы исследуем MotionLayout, применяя различные анимации и эффекты к виджету кнопки.
MotionLayouts доступен как часть ConstraintLayout 2.0, поэтому вы можете декларативно создавать все свои анимации, используя простой для чтения XML. Кроме того, поскольку он является частью ConstraintLayout, весь ваш код MotionLayout будет обратно совместим с API уровня 14!
Начало работы: ConstaintLayout 2.0
Начните с создания нового проекта. Вы можете использовать любые настройки, но при появлении запроса выберите «Включить поддержку Kotlin».
MotionLayout был представлен в ConstraintLayout 2.0 alpha1, поэтому вашему проекту потребуется доступ к версии 2.0 alpha1 или выше. Откройте файл build.gradle и добавьте следующее:
implementation
Как создать виджет MotionLayout?
Каждая анимация MotionLayout состоит из:
- Виджет MotionLayout: в отличие от других решений для анимации, таких как TransitionManager, MotionLayout предоставляет возможности только своим прямым дочерним элементам, поэтому вы обычно будете использовать MotionLayout в качестве корня файла ресурсов макета.
- MotionScene: вы определяете анимацию MotionLayout в отдельном XML-файле, называемом MotionScene. Это означает, что ваш файл ресурсов макета должен содержать только сведения о ваших представлениях, а не какие-либо свойства и эффекты анимации, которые вы хотите применить к этим представлениям.
Откройте файл activity_main.xml своего проекта и создайте виджет MotionLayout, а также кнопку, которую мы будем анимировать в этом руководстве.
<?xml version="1.0" encoding="utf-8"?>
Ваш пользовательский интерфейс должен выглядеть примерно так:
Создание MotionScene и установка некоторых ограничений
Файл MotionScene необходимо хранить в каталоге «res / xml». Если в вашем проекте еще нет этого каталога, тогда:
- Удерживая нажатой клавишу Control, щелкните папку «res».
- Выберите «Создать> Каталог ресурсов Android».
- Назовите этот каталог «xml».
- Откройте раскрывающееся меню «Тип ресурса» и выберите «xml».
- Нажмите «ОК».
Затем вам нужно создать XML-файл, в котором вы будете создавать MotionScene:
- Удерживая нажатой клавишу Control, щелкните папку «res / layout / xml» вашего проекта.
- Выберите «Создать> XML-файл ресурсов».
- Поскольку мы анимируем кнопку, я назову этот файл «button_MotionScene».
- Нажмите «ОК».
- Откройте файл «xml / button_motionscene» и добавьте следующий элемент MotionScene:
<?xml version="1.0" encoding="utf-8"?>
Каждый MotionScene должен содержать ConstraintSets, которые определяют ограничения, которые должны применяться к вашим виджетам в различных точках анимации. MotionScene обычно содержит как минимум два ограничения: одно представляет начальную точку анимации, а второе – конечную точку анимации.
При создании ConstraintSet вы указываете желаемую позицию виджета и его желаемый размер в этой точке анимации, которая переопределит любые другие свойства, определенные в файле ресурсов макета Activity.
Давайте создадим пару ConstraintSets, которые переместят кнопку из левого верхнего угла экрана в правый верхний угол.
<?xml version="1.0" encoding="utf-8"?>
Затем нам нужно уточнить, какой ConstraintSet представляет начальную точку анимации (constraintSetStart), а какой ConstraintSet представляет ее конечную точку (constraintSetEnd). Мы помещаем эту информацию в переход, который является элементом, который позволяет нам применять различные свойства и эффекты к самой анимации. Например, я также указываю, как долго должна длиться анимация.
<?xml version="1.0" encoding="utf-8"?>
Затем нам нужно убедиться, что наш виджет MotionLayout знает о файле MotionScene. Вернитесь к activity_main.xml и укажите MotionLayout в направлении файла «button_MotionScene»:
<?xml version="1.0" encoding="utf-8"?>
Сделай так, чтобы кнопка двигалась!
Чтобы запустить эту анимацию, нам нужно вызвать метод transitionToEnd(). Я собираюсь вызвать transitionToEnd () при нажатии кнопки:
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*
Установите этот проект на физический смартфон, планшет Android или виртуальное устройство Android (AVD) и нажмите кнопку. Виджет кнопки должен реагировать, перемещаясь из одного угла экрана в другой.
На этом этапе у нас есть проблема: как только кнопка переместится в верхний правый угол экрана, анимация закончится, и мы не сможем повторить ее, пока не выйдем и не перезапустим приложение. Как вернуть кнопку в исходное положение?
Мониторинг анимации с transitionToStart ()
Самый простой способ вернуть виджет в его начальный ConstraintSet – это отслеживать ход анимации, а затем вызывать transitionToStart () после завершения анимации. Вы отслеживаете ход анимации, присоединяя объект TransitionListener к виджету MotionLayout.
TransitionListener имеет два абстрактных метода:
- onTransitionCompleted (): этот метод вызывается после завершения перехода. Я буду использовать этот метод, чтобы уведомить MotionLayout о том, что он должен вернуть кнопку в исходное положение.
- onTransitionChange (): этот метод вызывается каждый раз, когда изменяется ход анимации. Этот прогресс представлен числом с плавающей запятой от нуля до единицы, которое я буду распечатывать в Logcat Android Studio.
Вот полный код:
import android.os.Bundle
import android.support.constraint.motion.MotionLayout
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*
Как только кнопка достигнет конца анимации, она должна автоматически перевернуть анимацию и вернуться в исходное положение.
Вы также можете отслеживать ход анимации в виде числа с плавающей запятой в Logcat Monitor Android Studio.
Создание более сложных анимаций: добавление ключевых кадров
В настоящее время наша кнопка движется по прямой от точки A к точке B. Мы можем изменить форму пути анимации, указав некоторые промежуточные точки. Если вы думаете о ConstraintSets как о «состояниях покоя» MotionLayout, то ключевые кадры – это точки, через которые виджет должен пройти на пути к своему следующему состоянию покоя.
MotionLayout поддерживает различные ключевые кадры, но мы сосредоточимся на:
- KeyPosition: изменяет путь, по которому виджет проходит во время анимации.
- KeyCycle: добавляет колебания вашей анимации.
- KeyAttribute: применяет новое значение атрибута в определенной точке во время перехода, например при изменении цвета или размера.
Все ключевые кадры должны быть размещены внутри KeyFrameSet, который, в свою очередь, должен быть помещен внутри элемента Transition. Откройте файл «button_motionscene.xml» и добавьте KeyFrameSet:
Изменение пути анимации с помощью KeyPosition
Давайте начнем с использования ключевого кадра KeyPosition, чтобы изменить путь, который наш виджет кнопки проходит через анимацию.
KeyPosition должно указывать следующее:
- motion: target: идентификатор виджета, на который влияет ключевой кадр, которым в данном случае является виджет кнопки.
- motion: framePosition: точка, в которой ключевой кадр применяется во время перехода, от начальной точки анимации (0) до конечной точки (100).
- app: percentX и motion: percentY: положение каждого ключевого кадра выражается как пара координат X и Y, хотя на результат этих координат будет влиять motion: keyPositionType проекта.
- motion: keyPositionType: управляет тем, как Android вычисляет путь анимации и, соответственно, координаты X и Y. Возможные значения: parentRelative (относительно родительского контейнера), deltaRelative (расстояние между начальной и конечной позицией виджета) и pathRelative (линейный путь между начальным и конечным состояниями виджета).
Я использую KeyPosition, чтобы преобразовать прямую линию анимации в кривую:
<Transition
motion:constraintSetStart="@+id/starting_set"
motion:constraintSetEnd="@+id/ending_set"
motion:duration="3000">
Нажмите на кнопку, и она пойдет по новому изогнутому маршруту по экрану.
Создание волн: добавление колебаний с помощью Keycycles
Вы можете применить несколько ключевых кадров к одной и той же анимации, если вы не используете одновременно несколько ключевых кадров одного типа. Давайте посмотрим, как мы можем добавить колебания к нашей анимации с помощью KeyCycles.
Как и в случае с KeyPosition, вам необходимо указать идентификатор целевого виджета (app: target) и точку, в которой должен применяться ключевой кадр (app: framePosition). Однако KeyCycle также требует нескольких дополнительных элементов:
- android: rotation: вращение, которое должно применяться к виджету при его перемещении по пути анимации.
- app: waveShape: Форма колебаний. Вы можете выбирать между грехом, квадратом, треугольником, пилой, обратным зубцом, косинусом и отскоком.
- app: wavePeriod: количество волновых циклов.
Я добавляю KeyCycle, который дает кнопке колебание «греха» на 50 градусов:
<Transition
motion:constraintSetStart="@+id/starting_set"
motion:constraintSetEnd="@+id/ending_set"
motion:duration="3000">
Попробуйте поэкспериментировать с разными стилями волн, поворотами и периодами волн, чтобы создать разные эффекты.
Масштабирование с помощью KeyAttribute
Вы можете указать другие изменения атрибутов виджета с помощью KeyAttribute.
Я использую KeyAttribute и android: scale, чтобы изменить размер кнопки, в середине анимации:
<?xml version="1.0" encoding="utf-8"?>
Добавление дополнительных эффектов анимации: настраиваемые атрибуты
Мы уже видели, как вы можете использовать KeyFrames для изменения свойств виджета при его перемещении от одного ConstraintSet к другому, но вы можете дополнительно настроить свою анимацию с помощью настраиваемых атрибутов.
CustomAttribute должен включать имя атрибута (attributeName) и используемое вами значение, которое может быть любым из следующих:
- customColorValue
- customColorDrawableValue
- customIntegerValue
- customFloatValue
- customStringValue
- customDimension
- customBoolean
Я собираюсь использовать customColorValue, чтобы изменить цвет фона кнопки с голубого на фиолетовый при перемещении по анимации.
Чтобы вызвать это изменение цвета, вам нужно добавить CustomAttribute в начало и конец ConstraintSet вашей анимации, а затем использовать customColorValue, чтобы указать цвет, которым должна быть кнопка в этой точке перехода.
<?xml version="1.0" encoding="utf-8"?>
Запустите этот проект на своем устройстве Android и нажмите кнопку, чтобы запустить анимацию. Кнопка должна постепенно менять цвет по мере приближения к концу ConstraintSet, а затем вернуться к своему исходному цвету на обратном пути.
Делаем вашу анимацию интерактивной
На протяжении этого урока мы создали сложную анимацию, состоящую из нескольких изменений атрибутов и эффектов. Однако после того, как вы нажмете кнопку, анимация будет циклически проходить через все эти различные этапы без каких-либо дополнительных действий с вашей стороны – было бы неплохо иметь больший контроль над анимацией?
В этом последнем разделе мы собираемся сделать анимацию интерактивной, чтобы вы могли перетаскивать кнопку вперед и назад по пути анимации и через все различные состояния, в то время как MotionLayout отслеживает скорость вашего пальца и сопоставляет ее со скоростью анимация.
Чтобы создать такую интерактивную перетаскиваемую анимацию, нам нужно добавить элемент onSwipe в блок Transition и указать следующее:
- motion: touchAnchorId: идентификатор виджета, который вы хотите отслеживать.
- motion: touchAnchorSide: сторона виджета, которая должна реагировать на события onSwipe. Возможные значения: справа, слева, сверху и снизу.
- motion: dragDirection: направление движения, которое вы хотите отслеживать. Выберите «dragRight», «dragLeft», «dragUp» или «dragDown».
Вот обновленный код:
</KeyFrameSet>
Запустите этот обновленный проект на своем устройстве Android – теперь вы сможете перемещать кнопку вперед и назад по траектории анимации, проводя пальцем по экрану. Обратите внимание, что эта функция кажется немного темпераментной, поэтому вам, возможно, придется немного провести пальцем по экрану, прежде чем вам удастся успешно «зацепить» кнопку!
Вы можете скачать этот полный проект с GitHub.
Подведение итогов
В этой статье мы увидели, как вы можете использовать MotionLayout для добавления сложных интерактивных анимаций в ваши приложения для Android и как настраивать эти анимации с помощью ряда атрибутов.
Как вы думаете, MotionLayout является улучшением существующих решений для анимации Android? Дайте нам знать в комментариях ниже!
Источник записи: https://www.androidauthority.com