- MotionLayout + RecyclerView = красивые анимированные списки
- Что такое MotionLayout?
- Шаг 1: создадим новый проект
- Шаг 2: добавим необходимые зависимости
- Шаг 3: создадим лэйаут
- Шаг 4: преобразуем ConstraintLayout в MotionLayout
- Шаг 5: добавим анимацию на ImageView
- Шаг 6: посмотрим, что получилось
- Шаг 7: добавим анимацию на CardView
- Шаг 8: добавим обработчик нажатий
- Шаг 9: добавим RecyclerView в activity_main.xml
- Шаг 10: создадим класс и фиктивные данные для примера
- Шаг 11: создадим адаптер и ViewHolder
- Шаг 12: заполним RecyclerView элементами
- Ещё кое-что
- Анимируем RecyclerView легко без перехода на ViewPager2
- Анимации Android RecyclerView на Kotlin
- Начнем с основ
- Анимации Android RecyclerView: объяснение свойств
- -Translate
- -Alpha
- -Rotate
- -Scale
- -Setting up
- Некоторые красивые примеры анимации
- Интерполяторы
MotionLayout + RecyclerView = красивые анимированные списки
В этой статье я расскажу и покажу, как создавать красивые анимированные списки на основе RecyclerView и MotionLayout. Аналогичный метод я использовал в одном из своих проектов.
От переводчика: репозиторий автора статьи — https://github.com/mjmanaog/foodbuddy.
Я его форкнул, чтобы перевести. Возможно, кому-то «русская версия» подойдёт больше.
Что такое MotionLayout?
Если вкратце, то MotionLayout — это подкласс ConstraintLayout, который позволяет с помощью XML описывать движения и анимацию расположенных на нём элементов. Подробнее — в документации и вот здесь с примерами.
Шаг 1: создадим новый проект
Назовём его, как душе угодно. В качестве активити выберем Empty Activity.
Шаг 2: добавим необходимые зависимости
В gradle-файл приложения добавим:
И запустим синхронизацию (Sync Now в правом верхнем углу).
Шаг 3: создадим лэйаут
Наш будущий элемент списка будет выглядеть так:
Элемент списка RecyclerView
В папке res/layout создадим файл item_food.
Внутри он выглядит так
Шаг 4: преобразуем ConstraintLayout в MotionLayout
Чтобы преобразовать ConstraintLayout в MotionLayout:
переключитесь в режим Split или Design;
в дереве компонентов (Component Tree) щёлкните правой кнопкой мыши на корневой элемент (в данном случае — clMain);
в появившемся меню выберите Convert to MotionLayout.
Как преобразовать ConstraintLayout в MotionLayout
Теперь мы можем работать с MotionLayout.
Содержимое файла item_food поменялось
В папке res Студия создала папку xml и положила в неё файл item_food_scene.xml:
Студия предупреждает (Warnings в нижней части экрана), что у элементов ImageView не заполнен тег contentDescription. Можете проигнорировать эти сообщения, а можете добавить в XML-разметке соответствующие теги (для чего они нужны, читайте здесь).
Шаг 5: добавим анимацию на ImageView
В дереве элементов выберите ivFood (ImageView с основной картинкой);
В редакторе MotionLayout выберите end;
У выделенного элемента ivFood выделите правую (End) опорную точку и перетащите её за правую (End) границу родительского элемента;
Картинка должна встать по центру родительского элемента;
Поменяйте значение атрибутов layout_height и layout_width на 300dp.
От переводчика: начальное состояние ImageView (его положение, ширина и высота) осталось без изменений, а его конечное состояние изменилось: он встанет по центру и увеличится в размере в два раза (с 150dp до 300dp).
Шаг 6: посмотрим, что получилось
Чтобы воспроизвести анимацию, которую мы только что настроили:
В редакторе MotionLayout выделите толстую стрелку, которая соединяет прямоугольники с надписями start и end;
В редакторе ниже станет доступным блок Transition;
Нажмите кнопку Play, чтобы воспроизвести анимацию.
Шаг 7: добавим анимацию на CardView
Порядок действий схож:
В дереве компонентов выделите cardView (constraintView с заголовком, описанием, калорийностью и оценкой);
В редакторе MotionLayout выберите end;
Выделите cardView в появившемся разделе ConstraintSet;
В разделе атрибутов элемента перейдите к группе Transforms;
Поменяйте значение атрибута alpha на 0.
От переводчика: у карточки с описанием блюда конечное состояние (end) от начального (start) отличается только значением параметра alpha. В конечном состоянии она будет скрыта (и скрываться она будет плавно).
Шаг 8: добавим обработчик нажатий
Чтобы анимация включалась, надо настроить обработчик нажатий:
В разделе атрибутов под OnClick добавьте новое поле (кнопка «+»);
В параметра targetId выберите значение ivFood;
Добавьте ещё одно поле;
Для параметра ClickAction выберите значение toggle.
В результате получится такая анимация:
Шаг 9: добавим RecyclerView в activity_main.xml
Шаг 10: создадим класс и фиктивные данные для примера
Шаг 11: создадим адаптер и ViewHolder
Тут ничего экзотического нет. Используем нашу FoodModel
Шаг 12: заполним RecyclerView элементами
В результате этих несложных действий получилась такая анимация:
Она вести 11 Мб.
Ещё кое-что
В файле item_food_scene.xml содержится описание анимации, которую мы настроили. Никто не мешает вам создавать и редактировать анимации в файлах сцены вручную.
Надеюсь, материал из этой статьи кому-то окажется полезным. Будет круто, если вы узнаете из неё что-то новое.
Источник
Анимируем RecyclerView легко без перехода на ViewPager2
Когда мы работаем с коллекциями и их отображением, перед многими из нас часто
встает выбор между ViewPager (теперь ещё и ViewPager2 ) и RecyclerView . Эти
компоненты похожи друг на друга по области применения, но серьезно отличаются
интерфейсом и реализацией. Начиная с support library 24.2.0 границы между
данными компонентами стали ещё более размытыми, т.к. появился вспомогательный
класс SnapHelper для автоматического доведения сhildView до
определенного положения на экране, и без устаревшего ViewPager стало проще
обходиться. С недавним релизом ViewPager2 , казалось бы, о старом ViewPager и о
практиках его имитации вообще можно забыть ( ViewPager2 — это по сути
RecyclerView с дополнительными вспомогательными классами, он позволяет
практически идентично повторить поведение ViewPager и сохраняет совместимость со
старым api).
Так ли это на самом деле? Лично для меня всё оказалось не так просто. Во-первых,
в классическом RecyclerView отсутствует интерфейс PageTransformer для
анимирования сhildView в зависимости от позиции (далее по тексту используется
понятие «позиционная анимация»). Во-вторых, неприятными сюрпризами долгожданного
ViewPager2 оказались модификатор класса final , который ставит крест на
переопределении метода onInterceptTouchEvent (компонент мало пригоден для
вложения горизонтальных списков в вертикальные), и приватность поля
recyclerView .
Итак, столкнувшись в очередной раз с трудностями позиционной анимации при
отображении коллекций с помощью RecyclerView и поковырявшись в ViewPager2 и
MotionLayout , я подумал, что позаимствовать принцип работы
ViewPager.PageTransformer для классической реализации RecyclerView а-ля
ViewPager2 не самая плохая идея.
Задача, в контексте которой это затевалось, была достаточно необычной:
- сделать компонент для отображения коллекции в горизонтальном и вертикальном
представлении - горизонтальный список должен повторять поведение ViewPager и пролистываться
со sticky-эффектом - при движении нижней “шторки” ( BottomSheetBehavior ) должна происходить
анимированная трансформация ориентации списка — выпадение элементов лесенкой - должна быть возможность выбора элемента из вертикального списка с
анимированным сдвигом остальных элементов влево и последующим превращением
вертикального списка в горизонтальный.
Запутались? Вот вам пример такого горизонтально-вертикального списка в
интернет-банкинг приложении «Мой кредит» Банка Хоум Кредит:
1. Делаем компонент для анимированного списка
Сам компонент было решено спроектировать как наследника ConstraintLayout с двумя
recyclerView внутри. Прогресс анимации берется из BottomSheetCallback нашего
BottomSheetBehavior :
У компонента есть метод transformation , принимающий прогресс “превращения” как
аргумент.
2. Решаем проблему позиционного анимирования
Реализацию анимации я начал с интерфейса для позиционной анимации — аналога
ViewPager.PageTransformer.
Идея была такой — есть абстрактный класс ItemViewTransformer с абстрактным
методом transformItemView , повторяющим сигнатуру метода transformPage интерфейса
ViewPager.PageTransformer :
В attachToRecycler происходит инициализация свойства recyclerView и слушателей
RecyclerView.AdapterDataObserver и RecyclerView.OnScrollListener :
После вызова updatePosition происходят вызовы метода transformItemView для
каждого видимого childView с передачей в аргументы текущей позиции относительно
левого края (такой расчет позиции справедлив только для childViews одинаковой
ширины/высоты с учетом отступов):
Начиная с этого момента, вы можете взять, например, свой старый добрый
pageTransformer , на который вы когда-то потратили так много времени, и
переиспользовать его код для recyclerView .
3. Sticky-эффект горизонтального списка
В примере выше sticky-эффект реализован как раз с помощью этого абстрактного
класса. В имплементации метода размер и положение описываем простейшими
кусочными функциями:
Аттачим наш BouncingTransformer сразу после инициализации адаптера и
recyclerView:
После компиляции мы получим пролистывание списка со sticky-эффектом:
В общем-то, ничто не мешает анимировать список, например, как колоду карт, и не
придется прибегать даже к помощи ItemDecoration .
4. Делаем универсальный прогресс-аниматор
Следующим этапом был реализован аналогичный интерфейс для выполнения
value-анимации с абстрактным методом onUpdate :
Здесь attachToRecycler инициализирует лишь свойство recyclerView :
Методом update задается прогресс анимации для видимой позиции или позиции
адаптера:
5. Трансформация списка
Теперь мы можем описать трансформацию “лесенкой” вертикального recyclerView в
имплементации метода onUpdate :
Аттачим точно так же, как предыдущий класс, прогресс берем из
BottomSheetCallback . После компиляции увидим следующее:
6. Эффект разбегания для горизонтального списка
Этой трансформации должен предшествовать эффект “разбегания” вьюшек в
горизонтальном списке:
Получаем желаемое поведение:
7. Анимация выбора элемента в вертикальном списке
При выборе элемента в вертикальном списке должна произойти анимированная
трансформация в горизонтальный список с пресетом в нем выбранного ранее
childView . Для достижения нужного эффекта удаляем остальные элементы из
вертикального адаптера. Анимацию удаления элементов реализуем на свой вкус, либо
нашим ItemViewAnimatorUpdater :
Либо классически с помощью ItemAnimator :
Получаем похожее поведение:
Завершаем трансформацию списка выездом правого видимого элемента горизонтального
списка:
После компиляции видим:
8. Результаты
По большому счету на этом реализация анимации завершена. Что в итоге мы
получили:
- отказались от использования ViewPager, что, как минимум, обещает лучшую
консистентность адаптеров, а значит и более удобный data building - получили преимущества ViewPager.PageTransformer — удобное позиционное
анимирование - сохранили преимущества RecyclerView — более экономное потребление ресурсов,
гибкую систему нотификации изменений адаптера, ItemAtimator, ItemDecoration - не добавляли новые зависимости в проект
- реализовали достаточно сложную анимационную последовательность на основе
всего двух новых абстрактных классов.
Надеюсь, эта статья окажется для вас полезной. Удачи!
Источник
Анимации Android RecyclerView на Kotlin
Простого функционального кода недостаточно для красивого современного приложения. Думаю, все согласны с тем, что сегодня приложение должно обладать красивым интерфейсом и показывать переходы и анимации.
Простого функционального кода недостаточно для красивого современного приложения. Думаю, все согласны с тем, что сегодня приложение должно обладать красивым дизайном и показывать переходы и анимации. Сегодня я попытаюсь объяснить один из этих аспектов, а именно анимации элементов RecyclerView в Android. Я буду использовать Android Studio и Kotlin. Наслаждайтесь 🙂
Начнем с основ
Прежде всего, вам нужно создать папку с анимацией для хранения файлов анимации.
res(right-click)->New->Android Resource Directory
» data-medium-file=»https://i0.wp.com/apptractor.ru/wp-content/uploads/2020/11/1-11.png?fit=612%2C113&ssl=1″ data-large-file=»https://i0.wp.com/apptractor.ru/wp-content/uploads/2020/11/1-11.png?fit=612%2C113&ssl=1″ svg+xml,%3Csvg%20xmlns=’http://www.w3.org/2000/svg’%20viewBox=’0%200%20612%20113’%3E%3C/svg%3E» alt=»Анимации Android RecyclerView на Kotlin» width=»612″ height=»113″ data-recalc-dims=»1″ data-lazy-src=»https://i0.wp.com/apptractor.ru/wp-content/uploads/2020/11/1-11.png?resize=612%2C113&ssl=1″/>
res(right-click)->New->Android Resource Directory
После этого щелкните правой кнопкой мыши папку с анимацией и создайте «Animation Resources File».
Анимации Android RecyclerView: объяснение свойств
Когда вы создадите файл ресурсов анимации, вы увидите в нем некоторые свойства. Я попытаюсь объяснить их, и после этого мы будем создавать наши анимации.
-Translate
Translate используется в основном для перемещения элементов по осям x и y. У него есть такие атрибуты:
FromXDelta и fromYDelta показывают, с какого направления будет появляться элемент. Если вы установите положительное значение для «fromXDelta», оно будет появляться с правой стороны экрана. Атрибуты ToDelta представляют, где элемент будет останавливаться. Обычно я использую атрибут toDelta в 0%. Потому что даже если вы установите «-100%», когда анимация закончится, элемент вернется на экран, и это будет выглядеть не очень красиво. И, наконец, «продолжительность» — это время анимации. Давайте посмотрим на анимацию со свойством только translate.
-Alpha
Alpha используется для определения непрозрачности. Это свойство в основном используется для анимации постепенного появления/исчезновения. Атрибуты указаны ниже:
Эффект постепенного появления и исчезновения анимации может быть достигнут с использованием атрибутов fromAlpha и toAlpha. Если вы используете значения, подобные приведенным выше, вы получите эту анимацию.
-Rotate
Свойство Rotate, как можно понять из названия, используется для анимации вращения для элементов представления.
Эти атрибуты вначале сбивали меня с толку, поэтому я постараюсь объяснить их как можно яснее. Атрибут FromDegrees представляет, с какого угла элемент будет разворачиваться. Представьте себе градусы и посмотрите на изображение сейчас. Элементы начинаются с угла 270 ° и вращаются по часовой стрелке. Атрибуты Pivot похожи на закрепление элемента в соответствии с их значением. Например, если вы установите pivotX: 100%, pivotY: 0% и fromDegrees: 90 °, приложение закрепит элемент в правом верхнем углу и соответственно повернет его. Анимацию можно увидеть на гифке ниже.
-Scale
Свойство Scale используется для масштабирования элементов. Этих атрибутов больше, чем других, поэтому давайте углубимся в них.
Атрибуты Pivot здесь выполняют немного другую функцию. Значение 50% для обоих атрибутов представляет центр элемента. Я установил это так, потому что хочу масштабировать их от центра. Атрибуты FromScale и ToScale используются для масштабирования элемента. 1 для исходного размера и 0 для начального размера. Эти атрибуты делаю то, что вы видите ниже.
-Setting up
Прежде всего, вам нужно определить View, который вы хотите анимировать, для элемента RecyclerView в адаптере. После этого вы можете использовать приведенный выше фрагмент кода в OnBindViewHolder, чтобы добавить свои анимации. Я хочу анимировать весь элемент, поэтому я определил представление карточки shopDetailParent в адаптере. Example_anims — это мой файл анимаций, поэтому вам нужно использовать в коде собственное имя файла.
Некоторые красивые примеры анимации
Интерполяторы
У нас есть последний атрибут — интерполяторы. Интерполяторы — это в основном поведение анимаций. Обычно анимация работает с линейным интерполятором. Этот интерполятор равномерно перемещает представление по каждому кадру анимации. (Все графики с этого момента взяты с jebware.com, вы можете зайти на сайт и попробовать интерполяторы с разными коэффициентами) И его график такой:
Но у других интерполяторов другие графики. Я покажу вам, как добавлять интерполяторы, и покажу пару примеров, после чего вы можете попробовать поработать с ними самостоятельно. Все, что вам нужно сделать, это добавить эту строку в свой set.
Интерполятор замедления заставит элементы продвигаться с внешней правой стороны экрана и замедлит их, когда они будут близки к конечной позиции.
Список интерполяторов от developer.android. Но также вы можете писать собственные интерполяторы.
Спасибо, что прочитали мою статью. Я пытался объяснить то, что знаю. Надеюсь, это поможет вам понять и сделать красивую анимацию для RecyclerView 🙂
Источник