- Советы для профессионального использования RecyclerView. Часть 2
- 1. ItemDecoration
- 2. ItemAnimator
- Анимации Android RecyclerView на Kotlin
- Начнем с основ
- Анимации Android RecyclerView: объяснение свойств
- -Translate
- -Alpha
- -Rotate
- -Scale
- -Setting up
- Некоторые красивые примеры анимации
- Интерполяторы
- Анимируем RecyclerView легко без перехода на ViewPager2
Советы для профессионального использования RecyclerView. Часть 2
Продолжая предыдущую статью, в этой я расскажу про ItemDecoration и ItemAnimator и постараюсь объяснить принцип их работы в RecyclerView на примере простого приложения, которое доступно на Github.
1. ItemDecoration
ItemDecoration используется для декорирования элементов списка в RecyclerView .
С помощью ItemDecoration вы сможете добавлять разделители между view -компонентам, выравнивать их или разбивать равными промежутками. Чтобы добавить простой разделитель между view -компонентами, воспользуйтесь классом DividerItemDecoration , который можно найти в библиотеке поддержки версии 25.1.0 и выше. Следующий фрагмент кода демонстрирует его реализацию:
Лучший способ создания собственного разделителя — расширение класса RecyclerView.ItemDecoration . В примере приложения я использовал GridLayoutManager и применил CharacterItemDecoration к RecyclerView :
Здесь CharacterItemDecoration устанавливает смещение (англ. offset) на 50 пикселей в своём конструкторе и переопределяет getItemOffsets(. ) . Внутри метода getItemOffsets() каждое поле outRects определяет количество пикселей, которые необходимо установить для каждого view -компонента, подобно внутренним и внешним отступам. Поскольку я использовал GridLayoutManager и хотел настроить равные расстояния между элементами сетки, я установил отступ справа в 25 пикселей (т.е. offset/2) для каждого чётного элемента и отступ слева в 25 пикселей для каждого нечётного элемента, сохраняя при этом верхний отступ одинаковым для всех элементов.
2. ItemAnimator
ItemAnimator используется для анимации элементов или view -компонентов внутри RecyclerView .
Давайте сделаем наше приложение «Инстаграмоподобным», расширив DefaultItemAnimator и переопределив несколько методов.
Метод canReuseUpdatedViewHolder(. ) определяет, будет ли один и тот же ViewHolder использоваться для анимации, если данные этого элемента изменятся. Если он возвращает false , то оба ViewHolders — старый и обновленный — передаются в метод animateChange(. ) .
RecyclerView вызывает метод recordPreLayoutInformation(. ) до начала отрисовки layout . ItemAnimator должен записывать необходимую информацию о view -компоненте до того, как он будет перезаписан, перемещен или удалён. Данные, возвращаемые этим методом, будут переданы соответствующему методу анимации (в нашем случае это animateChange(. ) ).
RecyclerView вызывает метод animateChange(. ) , когда элемент адаптера присутствует одновременно до и после отрисовки после вызова метода notifyItemChanged(int) . Этот метод также можно использовать, при вызове notifyDataSetChanged() , если при этом в адаптере используются стабильные идентификаторы. Это необходимо для того, чтобы RecyclerView мог переиспользовать view -компоненты в тех же ViewHolders . Обратите внимание на то, что этот метод принимает в качестве аргументов: (ViewHolder oldHolder, ViewHolder newHolder, ItemHolderInfo preInfo, ItemHolderInfo postInfo). Поскольку мы повторно используем ViewHolder , оба — oldHolder и newHolder — одинаковы.
Всякий раз, когда пользователь дважды кликает на любой элемент, вызывается следующий метод:
Это запускает всю цепочку вызовов: canReuseUpdatedViewHolder(. ) , recordPreLayoutInformation(. ) и, в конечном итоге, animateChange(. ) в ItemAnimator , который, в свою очередь, анимирует элемент списка и иконку сердечка в этом элементе (пример на гифке выше).
Это вторая часть серии статей про RecyclerView . Если пропустили первую часть, то читайте её здесь.
Ещё несколько хороших статей на тему RecyclerView :
Источник
Анимации 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 🙂
Источник
Анимируем 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 - не добавляли новые зависимости в проект
- реализовали достаточно сложную анимационную последовательность на основе
всего двух новых абстрактных классов.
Надеюсь, эта статья окажется для вас полезной. Удачи!
Источник