- RecyclerView
- getItemCount()
- onCreateViewHolder
- onBindViewHolder()
- Горизонтальная прокрутка
- Оптимизация
- Кастомный ItemDecoration для RecyclerView
- 1. Простой ItemDecoration : DividerItemDecoration
- 2. Custom ItemDecoration
- 2.1. Decoration в зависимости от позиции элемента
- 2.2. Удаляем ItemDecoration в конце списка
- 2.3. Оформление на основе типа View
- Русские Блоги
- RecyclerView ItemDecoration объяснение и практика расширенных функций
- ItemDecoration
- getItemOffsets()
- onDraw()
- Реализуйте эффект оси времени с помощью ItemDecoration
- onDrawOver и индекс.
- резюме
- напоминать
RecyclerView
Компонент RecyclerView появился в Android 5.0 Lollipop и находится в разделе Containers. Для простоты буду называть его списком, хотя на самом деле это универсальный элемент управления с большими возможностями.
Раньше для отображения прокручиваемого списка использовался ListView. Со временем у него обнаружилось множество недостатков, которые было трудно исправить. Тогда решили создать новый элемент с нуля.
Вначале это был сырой продукт, потом его доработали. На данном этапе можно считать, что он стал полноценной заменой устаревшего ListView.
Схематично работу RecyclerView можно представить следующим образом. На экране отображаются видимые элементы списка. Когда при прокрутке списка верхний элемент уходит за пределы экрана и становится невидимым, его содержимое очищается. При этом сам «чистый» элемент помещается вниз экрана и заполняется новыми данными, иными словами переиспользуется, отсюда название Recycle.
Компонент RecyclerView не является родственником ListView и относится к семейству ViewGroup. Он часто используется как замена ListView, но его возможности шире.
Следует сказать, что при работе с ним приходится писать много кода, который пугает новичков. Если с RecyclerView работать не постоянно, то порой забываются детали и сложно вспомнить необходимые шаги. Многие просто сохраняют отдельные шаблоны и копируют в разные проекты.
Внешний вид можно представить не только в виде обычного списка, но и в виде сетки. При необходимости можно быстро переключиться между разными типами отображения.
Для размещения своих дочерних элементов используется специальный менеджер макетов LayoutManager. Он может быть трёх видов.
- LinearLayoutManager — дочерние элементы размещаются вертикально (как в ListView) или горизонтально
- GridLayoutManager — дочерние элементы размещаются в сетке, как в GridView
- StaggeredGridLayoutManager — неравномерная сетка
Можно создать собственный менеджер на основе RecyclerView.LayoutManager.
RecyclerView.ItemDecoration позволяет работать с дочерними элементами: отступы, внешний вид.
ItemAnimator — отвечает за анимацию элементов при добавлении, удалении и других операций.
RecyclerView.Adapter связывает данные с компонентом и отслеживает изменения.
- notifyItemInserted(), notifyItemRemoved(), notifyItemChanged() — методы, отслеживающие добавление, удаление или изменение позиции одного элемента
- notifyItemRangeInserted(), notifyItemRangeRemoved(), notifyItemRangeChanged() — методы, отслеживающие изменение порядка элеметов
Стандартный метод notifyDataSetChanged() поддерживается, но он не приводит к внешнему изменению элементов на экране.
Программисты со стажем знают, что для создания «правильного» ListView нужно было создавать класс ViewHolder. В старых списках его можно было игнорировать. Теперь это стало необходимым условием.
Общая модель работы компонента.
Мы рассмотрим только базовый пример для быстрого знакомства. В реальных проектах примеры будут гораздо сложнее, чтобы обеспечить другие функциональные возможности — обработка жестов, анимация, динамическое удаление и добавление элементов.
Размещаем компонент в макете экрана через панель инструментов. Но сначала добавим зависимость.
Создадим макет для отдельного элемента списка. Варианты могут быть самыми разными — можно использовать один TextView для отображения строк (имена котов), можно использовать связку ImageView и TextView (имена котов и их наглые морды). Мы возьмём для примера две текстовые метки. Создадим новый файл res/layout/recyclerview_item.xml.
Добавим компонент в разметку экрана активности.
Минимальный код для запуска.
Пока ничего сложного, но выводить такой список ничего не будет. Нужен адаптер и данные для отображения. В адаптере описывается способ связи между данными и компонентом.
Начнём по порядку, чтобы запомнить последовательность. Для начала создадим обычный класс и в конструкторе передадим список строк. Список будет содержать имена котов.
Класс MyViewHolder на основе ViewHolder служит для оптимизации ресурсов. Новый класс добавим в состав нашего созданного ранее класса.
В созданном классе нужно просто перечислить используемые компоненты из макета для отдельного элемента списка. В нашем примере задействованы два TextView, инициализируем их через идентификаторы.
Создадим адаптер — наследуем наш класс от класса RecyclerView.Adapter и в качестве параметра указываем созданный нами MyViewHolder. Студия попросит реализовать три метода.
getItemCount()
Как правило данные являются однотипными, например, список или массив строк. Адаптеру нужно знать, сколько элементов нужно предоставить компоненту, чтобы распределить ресурсы и подготовиться к отображению на экране. При работе с коллекциями или массивом мы можем просто вычислить его длину и передать это значение методу адаптера getItemCount(). В простых случаях мы можем записать код в одну строчку.
onCreateViewHolder
В методе onCreateViewHolder нужно указать идентификатор макета для отдельного элемента списка, созданный нами ранее в файле recyclerview_item.xml. А также вернуть наш объект класса ViewHolder.
onBindViewHolder()
В методе адаптера onBindViewHolder() связываем используемые текстовые метки с данными — в одном случае это значения из списка, во втором используется одна и та же строка.
Должно получиться следующее.
Подключаем в активности. Создадим пока бессмысленный список строк, который передадим в адаптер.
Запускаем ещё раз.
Вариант с числами нам не интересен, поэтому добавим котов. Имена котов и кошек разместим в ресурсах в виде массива в файле res/values/strings.xml.
Создадим новую функцию для получения списка котов из ресурсов и передадим его адаптеру.
Горизонтальная прокрутка
Можем указать горизонтальный вариант прокрутки. Остальной код менять не придётся.
А можно вообще обойтись только XML-декларацией.
Оптимизация
При прокрутке под капотом выполняется сложная работа по обновлению контента. Поэтому не следует перегружать элементы списка сложной структурой и не перебарщивайте с вложенными элементами, а также нужно следить за оптимизацией, чтобы избежать лагов.
При работе с изображениями старайтесь использовать готовые библиотеки Picasso, Glide, Fresco и т.д.
Если картинки загружаются с сервера, неплохо заранее вычислять их размеры и пропорции. В некоторых случаях желательно позаботиться, чтобы картинки были одного размера (если это возможно).
Не перегружайте лишним кодом метод onBindViewHolder(). Только самое необходимое.
Источник
Кастомный ItemDecoration для RecyclerView
Предисловие переводчика:
Оригинальная статья содержит GIF-анимации с демонстрацией работы кода (т. е. результат). К сожалению, мне не удалось вставить их в статью, т. к. я использовал новый редактор от Хабра, а он очень криво работает с изображениями 🙂 Для просмотра анимаций, вы можете перейти к оригинальной статье
Как-то раз мне нужно было создать собственный ItemDecoration, и я обнаружил, что в Интернете. почти нет ответов на этот вопрос. Надеюсь, что эта статья будет кому-нибудь полезна.
Простой ItemDecoration
Кастомный ItemDecoration
ItemDecoration основанный на позиции
ItemDecoration без отрисовки после последнего списка
ItemDecoration основанный на типе View
1. Простой ItemDecoration : DividerItemDecoration
Основной вариант использования может быть реализован с помощью DividerItemDecoration предоставляемый Android-ом.
Создает разделитель RecyclerView.ItemDecoration который можно использовать с LinearLayoutManager.
@param context […] будет использоваться для доступа к ресурсам.
@param orientation […] должен быть #HORIZONTAL или #VERTICAL.
Что вам нужно, так это установить правильную ориентацию, а затем предоставить drawable-ресурс, используемый для разделения каждого элемента.
Преимущества
Предоставляется самим Android
Прост в использовании
Недостатки
Как было упомянуто: ограниченные варианты использования — в качестве разделителя пустым пространством или линией.
Ограничение при использовании и «бесконечной» прокруткой (или пагинацией): декоратор будет отрисован для каждого элемента, в том числе и последнего. В большинстве случаев мы этого не хотим.
2. Custom ItemDecoration
Для лучшего контроля и более сложных вещей мы расширим RecyclerView.ItemDecoration.
Нам доступны 3 метода:
getItemOffsets используется для определения расстояния между элементами.
onDraw используется для отрисовки в пространстве между элементами.
onDrawOver то же, что и onDraw, только вызывается после того, как сам элемент отрисован.
? Cм. официальную документацию: getItemOffsets , onDraw , onDrawOver .
? Обратите внимание, что в примерах используется горизонтальная ориентация, но то же самое можно сделать и с вертикальной.
2.1. Decoration в зависимости от позиции элемента
Для начала простой пример: давайте украсим элементы с нечетной позицией в адаптере.
Кастомный ItemDecoration на основе позиции View
Главный метод здесь здесь parent.getChildAdapterPosition (view)
Он возвращает позицию переданной View в адаптере. См. полную документацию.
⚠️ Не путать с дочерними позициями родителей ( parent.children — это элементы, отображаемые на экране).
⚠️ Не забудьте обработать случай с RecyclerView.NO_POSITION , т. к. getChildAdapterPosition может вернуть -1.
2.2. Удаляем ItemDecoration в конце списка
Это наиболее распространенный вариант использования на StackOverflow, о котором вы спрашиваете. Это кастомный ItemDecoration , основанный на позиции элемента в адаптере.
Пользовательское оформление DividerItemDecoration, за исключением последнего элемента
Исключим последний элемент, добавив if (childAdapterPosition == adapter.itemCount-1) .
⚠️ Нужно помнить, что parent.adapter может быть null.
? Обратите внимание, что в большинстве случаев вам, вероятно, нужен только интервал между вашими элементами (за исключением последнего). Нет необходимости переопределять метод onDraw , достаточно установить правильный размер Rect в методе getItemsOffsets.
Пользовательский DividerItemDecoration, с добавлением интервала между элементами, за исключением последнего
2.3. Оформление на основе типа View
В этом примере у нас есть 2 типа элементов, показанных черным и серым. Мы оформляем элементы синими и красными Drawable в зависимости от типа View (объявленных в Adapter-е ).
Пользовательский ItemDecoration в зависимости от типа View
Главная строчка кода здесь здесь — adapter.getItemViewType(childAdapterPosition) . Нам нужно переопределить метод getItemViewType в нашем адаптере.
Он возвращает тип View элемента по позиции для повторного использования View. […] Подумайте над тем, чтобы использовать id-ресурсы для уникальной идентификации типов View.
См. официальную документацию getItemViewType .
Как только вы сможете определить тип вашего элемента, вы можете установить правильный интервал и украсить его по своему желанию ?.
Вы можете найти полный код в моём GitHub репозитории.
Источник
Русские Блоги
RecyclerView ItemDecoration объяснение и практика расширенных функций
Несомненно, RecyclerView является одним из наиболее важных системных компонентов в мире Android, его появление заключается в эффективной замене ListView и GridView. В то время его появление решало большую проблему для меня. Эта потребность заключалась в том, чтобы загружать список приложений горизонтально на интерфейсе ТВ-бокса. Поскольку ListView не имеет функции горизонтальной загрузки, а открытый исходный код HorizontalListView в сети не удовлетворяет потребности, мы можем только Определите ViewGroup для удовлетворения требований, но механизм утилизации не идеален, поэтому производительность не очень хорошая, поэтому, когда появился RecyclerView, я впервые принял его и рекомендовал, чтобы члены группы разработчиков Android поняли его.
Но позже я обнаружил, что RecyclerView является более сложным, чем ListView, но в некоторых местах он более сложный: он делегирует больше возможностей самому разработчику, например, макету, такой как разделительная линия ITEM, например, отслеживание щелчков и так далее. Но это всегда хорошо, поэтому мы тратим больше времени на изучение. Мы обычно разрабатываем в соответствии с базовым использованием RecyclerView для достижения большинства потребностей, но в некоторых сценариях этого далеко недостаточно, например, мы не хотим ограничиваться LinearLayoutManager Если мы хотим определить LayoutManager сами, нам нужно определить эффект оси времени, мы хотим добиться замечательной анимации добавления и удаления и т. Д. Чтобы решить проблему в этих случаях, нам нужно иметь достаточное понимание самого RecyclerView.
Сегодня в этой статье не говорится о базовых знаниях и использовании RecyclerView, но это интересный пункт знаний ItemDecoration.
ItemDecoration
Английское значение «Декорирование» — это значение «декорирование». Если оно расширено здесь, оно должно быть связано с оформлением интерфейса RecyclerView. Общим является разделительная линия.
Когда мы используем ListView, нам нужно использовать его только в файле XML android:divider Это нормально, но, к сожалению, RecyclerView не имеет соответствующего контроля.
Мы создаем новый проект и добавляем RecyclerView на страницу. Создайте соответствующий адаптер, загрузите файл макета, здесь файл макета очень прост, это TextView, а затем инициализируйте его в Activity.
Вы можете видеть, что все параметры смешаны. Ради красоты, необходима разделительная линия размером 1 пиксель. Прежде я обычно устанавливаю ее topMargin или bottomMargin в файле макета элемента, чтобы мы могли изменить ее в соответствующем адаптере.
Эффект заключается в следующем:
Теперь мы также можем добиться этого, добавив ItemDecoration в RecyclerView.
Прежде всего, нам нужно настроить ItemDecoration. В соответствии с текущими требованиями нам нужно реализовать только один его метод.
Затем добавьте его в RecyclerView в Activity.
Эффект заключается в следующем:
getItemOffsets()
Мы можем видеть, что пользовательский TestDividerItemDeoration реализует только один метод, getItemOffsets (). В методе четыре параметра.
- Rect outRect
- View view
- RecyclerView parent
- RecyclerView.State state
Что делают эти четыре параметра? Мы также можем нажать клавишу Ctrl в AndroidStudio, чтобы щелкнуть имя метода, и мы сможем добраться до места, где он вызывается.
Мы обращаем внимание на эту строку кода java mItemDecorations.get(i).getItemOffsets(mTempRect, child, this, mState); Легко узнать, что outRect — это Rect со всеми 0. представление относится к элементу в RecyclerView. Родителем является сам RecyclerView, а состояние — это состояние.
Мы можем увидеть эту картинку ниже.
Зеленая область представляет ItemView в RecyclerView, а внешняя оранжевая область представляет собой соответствующий outRect, который является областью смещения ItemView и других компонентов, что эквивалентно свойству margin. Переписав метод getItemOffsets (), затем указав top и left в outRect Справа, снизу можно контролировать интервал во всех направлениях.Обратите внимание, что все эти свойства являются смещениями, которые относятся к смещениям во всех направлениях ItemView.В приведенном выше примере я установил outRect.top = 1; Таким образом, между каждым ItemView есть разрыв в 1 пиксель, и этот разрыв в 1 пиксель показывает цвет фона ниже, поэтому он выглядит как разделитель, который обеспечивает простой эффект разделения, но этот метод разделения только Может ли это зависеть от цвета фона, если я хочу настроить цвет разделительной линии? На этот раз мы поговорим о новом имени метода onDraw ().
onDraw()
OnDraw () — это очень важный метод в каждом представлении в Android, используемый для рисования эффекта пользовательского интерфейса компонента, поэтому он естественно используется для рисования внешнего вида в ItemDecocration. Давайте посмотрим на его объявление метода.
java public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state);
Вы можете видеть, что он передает объект параметра Canvas, поэтому он может рисовать. Но как нарисовать это?
Фактически, он используется в сочетании с предыдущим методом getItemOffsets. GetItemOffsets растягивает верхний, нижний, левый и правый интервалы ItemView, а метод onDraw определяет интервал содержимого, которое будет отображаться, путем вычисления координатной позиции каждого ItemView и его значения outRect.
Предположим, мы хотим создать красную разделительную линию высотой 2 px, затем нам нужно нарисовать прямоугольник высотой 2 px над верхней позицией каждого ItemView, а затем залить цвет красным.
Стоит отметить, что getItemOffsets предназначен для каждого ItemView, а метод onDraw предназначен для самого RecyclerView, поэтому в методе onDraw вам нужно пройти через ItemView, видимый на экране, получить их информацию о положении, а затем нарисовать соответствующие разделительные линии.
Давайте посмотрим на эту принципиальную схему ниже
Чтобы облегчить наблюдение, я сделал цвет первой разделительной линии прозрачным, мы видим, что область, нарисованная каждой разделительной линией, фактически является областью между outRect.top и ItemView.top, поэтому нам нужно использовать метод getOffsets Когда позиция смещена, записывается расстояние между каждым itemView вверх.Логика заключается в том, чтобы пройти View на экране и затем нарисовать разделительную линию.
Затем мы можем добавить ColorDividerItemDecoration к соответствующему RecyclerView в Activity.
Эффект заключается в следующем:
На этом этапе красная разделительная линия готова.
Но следует отметить, что метод onDraw может не только рисовать простые линии, но и имеет Canvas, поэтому речь не идет о рисовании круга, прямоугольника, дуги или рисунка. Чтобы улучшить техническое содержание этого кода, мы будем использовать ItemDecoration для достижения эффекта временной оси.
Реализуйте эффект оси времени с помощью ItemDecoration
Сначала начните кодировать и проектировать, или сначала подумайте. Подумайте о том, что мы собираемся сделать или как это сделать.
Мы можем видеть, что белый рисунок слева — это, вероятно, график, который будет нарисован на нашей временной оси. Мы используем метод getItemOffsets, чтобы установить левый и верхний интервал ItemView. Затем определите начальные координаты оси, фигуры или рисунка узла средней оси. Мы можем использовать ItemView для разложения соответствующих фрагментов оси времени, как показано ниже.
В основном это определение некоторых параметров, таких как DividerHeight. Обратите внимание, что этот DividerHeight относится не к значению интервала ItemView вверх, но к высоте соответствующего ItemDecoration. Координаты центра (centerX, centerY), а также начальные координаты верхней и нижней осей. С этими параметрами мы можем легко кодировать.
Тогда эффект будет следующим:
Это не очень красиво, мы пытаемся изменить сплошной круг узла на полый круг.
Эффект заключается в следующем:
Это намного красивее.
В то же время мы можем использовать иконки для замены кругов или кругов.
Значок выше выглядит лучше.
Следует отметить, что метод onDraw ItemDecoration рисуется в ItemView, то есть ItemView может охватывать содержимое ItemDecoration. Мы можем проверить это, нарисовать полный круг на границе между временной шкалой и ItemView и наблюдать за ее эффектом.
Как вы можете видеть, в перекрывающейся области круг действительно покрывается содержимым ItemView.
Вы можете подумать, может ли контент ItemDecoration накладываться на контент ItemView?
Ответ — да, но не в методе onDraw (), а в другом методе onDrawOver ().
onDrawOver и индекс.
Реальные приложения или сайты часто имеют такие рейтинги, как:
Или так.
Эти углы нарисованы на ItemView, и теперь с ItemDecoration мы можем легко и элегантно реализовать его.
Например, мы хотим достичь рейтинга продаж книг. У нас есть грубый набросок.
Тогда мы можем закодировать.
Файл макета:
Соответствующий код адаптера:
Затем выполните соответствующую обработку данных в Activity, данные здесь для тестирования, так что это более произвольно.
Окончательный эффект заключается в следующем:
Кто-то думает, нельзя ли выполнить такую операцию через файл макета в ItemView? Да, действительно возможно определить угловую метку «Флаг» в каждом файле макета ItemView, а затем решить, следует ли загружать угловую метку в соответствии со значением позиции в методе onBindViewHolder адаптера.
Но здесь нужно проиллюстрировать метод onDrawOver в ItemDecoration, чтобы показать, что он позволяет рисовать изображение ItemDecoration поверх содержимого ItemView. На самом деле красота ItemDecoration намного лучше.
резюме
Настройка ItemDecoration обычно требует переписать 3 метода по мере необходимости.
* getItemOffsets расширяет пространство в верхнем, нижнем, левом и правом направлениях ItemView
* onDraw рисует графику ниже содержимого ItemView
* onDrawOver рисует графику поверх содержимого ItemView.
напоминать
Из-за длины статьи, наиболее захватывающего содержания ItemDecoration мне нужно написать еще одну статью, то есть настроить голову в RecyclerView или прикрепить голову через ItemDecoration. Я считаю, что все понимают концепцию головы, и теперь ее можно элегантно достичь с помощью ItemDecoration. Помните слово «элегантный», и все дороги ведут в Рим, но некоторые люди элегантны, а некоторые, кажется, заняты. Итак, в названии статьи я поставил слово, называемое маленьким десертом, которое очень приятно кушать, а также удобно использовать ItemDecoration.
Источник