Анимация в Android: переходы, ч. 1

Анимации в приложениях появились уже достаточно давно, и их красота, а вместе с ней и сложность, растут практически с каждым днём. Исходя из того, что анимация в привычном для человека понимании - это набор кадров, меняющихся с определенной задержкой, я решил начать изучение анимаций в Android с самых азов.
Анимация с помощью Transition представляет собой изменение свойств объекта (View), исходя из местоположения объекта на экране и примененного эффекта. С момента появления Transition в Android (с выхода версии 4.4 KitKat), появилось понятие сцены (Scene), и переход между двумя сценами это и есть Transition. Грубо говоря, чтобы сделать анимацию, нужна начальная сцена и конечная сцена. Например, чтобы сделать анимированное увеличение какого-либо объекта, можно сделать 1 лэйаут, затем скопировать его, и у копии сделать размер элемента больше. В итоге можем получить что-то подобное:
Таких анимаций можно сделать сколько угодно и разной сложности, всё зависит от фантазии разработчика (ну или дизайнера). В моем конкретном случае я использовал механизм Transition для плавного перехода между экранами. Исходя из этого, сценами будут являться уже лэйауты двух активити (или фрагментов), между которыми будет осуществляться переход.
Рис 1. Наглядное представление работы Transition для перехода между экранами
Практическое применение

Для начала нужно включить отображение Transitions, либо в стилях:
либо в самой активити:
Далее необходимо задать эффекты (типы Transition). Опишу самые распространенные:

- ChangeBounds: отвечает за изменение координат и размеров элементов внутри лэйаута;
- Fade: плавное появление (Fade.IN) или исчезновение (Fade.OUT) элемента;
- Slide: позволяет элементу "выезжать" (или "прибегать") из-за выбранного края;
- ChangeImageTransform: анимирует матричный переход изображения внутри ImageView. C помощью него можно плавно менять размер изображения и scaleType;
- ChangeClipBounds: анимирует изменение параметра clipBounds у элементов;
- AutoTransition: набор эффектов changeBouns, Fade.IN, Fade.OUT. Этот набор по умолчанию используется всеми элементами.
Кроме этого всегда можно написать свой собственный Transition, который не будет иметь ничего общего с вышеперечисленными.

Я решил повторить эффект с рисунка 2 (ниже). В моем случае понадобились эффекты changeBounds и changeImageTransform.

Далее верстаем два лэйаута (layout). У view, которые будут подвергнуты анимации, необходимо задать параметр transitionName, он задается на обоих лэйаутах одинаковый, тем самым обозначаются начальная и конечная сцены.
После этого в следующее активити (activity) нужно передать какие-то данные, которые будут отображаться, а также параметры для воспроизведения анимации - ActivityOptions.

iv1.setOnClickListener {
startActivity(Intent(this, ImageActivity::class.java).putExtra("photo", R.drawable.honeycomb), ActivityOptions.makeSceneTransitionAnimation(this, iv1, "photo").toBundle())
}
Как можно увидеть из примера кода, в качестве параметров принимается transitionName и view.

Совсем забыл про эффекты. В ресурсах нужно добавить директорию transition, там создать transitionSet и прописать эффекты, которые вам нужны.
Далее возвращаемся в стили и прописываем transitionSet для анимации входа в активити и выхода из активити.
Конечно же, можно использовать разные наборы, я использовал одинаковые.

Самое время посмотреть, для чего всё это делалось.
Выглядит неплохо, при том, что мы вообще не думали про жизненный цикл активити. Пойдем дальше: провернем такой же эффект, только уже с холдером recyclerView. Всё абсолютно так же, как и в предыдущем случае: задаем одинаковый transitionName у элементов холдера и у элементов целевого активити (target activity / result activity).
Напишем простенький адаптер с колбэком (callback), который по клику на холдер (holder) будет возвращать какие-то данные для следующего активити, а также вью, которые участвуют в анимации. Так как в этом случае я задал 2 view для анимации, воспользуемся перегрузкой функции makeSceneTransitionAnimation, которая принимает в себя переменный массив элементов Pair<View, String>, соответственно, каждый такой элемент передает view и привязанный к нему TransitionName.
Запускаем…
Очень даже хорошо, а главное быстро.

Для написания этой статьи я использовал информацию с поста на Habr: https://habr.com/ru/post/243363/, оттуда же примеры анимаций в начале статьи. Также изучил официальную документацию на портале разработчиков Google: https://developer.android.com/training/transitions/start-activity.
Спасибо за внимание!
BytePace © Все права защищены