Я изучал RecyclerView
и был удивлен, увидев, что RecyclerView
не имеет onItemClickListener()
.
У меня два вопроса.
Главный вопрос
Я хочу знать, почему Google удалили onItemClickListener()
?
Есть проблема с производительностью или что-то еще?
Вторичный вопрос
Я решил свою проблему, написав onClick
в моем RecyclerView.Adapter
:
public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
public TextView txtViewTitle;
public ImageView imgViewIcon;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title);
imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon);
}
@Override
public void onClick(View v) {
}
}
Это нормально / есть ли лучший способ?
java
android
android-recyclerview
Тарун Варшней
источник
источник
QUESTION
Ответы:
tl; dr 2016 Используйте RxJava и PublishSubject для предоставления Observable для кликов.
Исходное сообщение:
С момента введения
ListView
,onItemClickListener
было проблематично. В тот момент, когда у вас есть прослушиватель щелчков для любого из внутренних элементов, обратный вызов не будет запущен, но он не был уведомлен или хорошо документирован (если вообще), поэтому возникло много путаницы и SO вопросов по этому поводу.Учитывая, что
RecyclerView
это делает шаг вперед и не имеет понятия строки / столбца, а скорее произвольно выложенного количества дочерних элементов, они делегировали onClick каждому из них или реализации программиста.Думайте
Recyclerview
не какListView
замена 1: 1, а как более гибкий компонент для сложных случаев использования. И, как вы говорите, ваше решение - это то, что Google ожидал от вас. Теперь у вас есть адаптер, который может делегировать onClick интерфейсу, переданному конструктору, что является правильным шаблоном для обоихListView
иRecyclerview
.а затем на вашем адаптере
Теперь посмотрите на этот последний фрагмент кода:
onCreateViewHolder(ViewGroup parent, int viewType)
подпись уже предлагает различные типы представлений. Для каждого из них вам также потребуется отдельный видоискатель, и впоследствии у каждого из них может быть свой набор кликов. Или вы можете просто создать общий видоискатель, который принимает любой вид и одинonClickListener
и применяется соответственно. Или делегируйте один уровень оркестратору, чтобы несколько фрагментов / действий имели один и тот же список с различным поведением щелчка. Опять же, вся гибкость на вашей стороне.Это действительно необходимый компонент, довольно близкий к тому, что было до наших внутренних реализаций и улучшений
ListView
. Хорошо, что Google наконец признает это.источник
onBindViewHolder(holder, position)
, где информация должна быть заполнена.getPosition()
устарел "Этот метод устарел, поскольку его значение неоднозначно из-за асинхронной * обработки обновлений адаптера. Пожалуйста, используйте {@link #getLayoutPosition ()} или * {@link #getAdapterPosition ()} в зависимости от вашего варианта использования. "viewHolder.getPosition();
Почему RecyclerView не имеет
onItemClickListener
Это
RecyclerView
набор инструментов, в отличие от старого,ListView
он имеет меньше встроенных функций и большую гибкость. ЭтоonItemClickListener
не единственная функция, удаляемая из ListView. Но у него есть много слушателей и методов, чтобы расширить его по своему вкусу, он намного мощнее в правильных руках;).На мой взгляд, самая сложная функция, которая была удалена,
RecyclerView
- это быстрая прокрутка . Большинство других функций могут быть легко повторно реализованы.Если вы хотите узнать, какие еще классные функции
RecyclerView
добавлены, прочитайте этот ответ на другой вопрос.Эффективное использование памяти - встроенное решение для onItemClickListener
Это решение было предложено от Hugo Visser , в Android GDE, сразу после того,
RecyclerView
был освобожден. Он сделал класс без лицензии доступным для вас, чтобы просто вставить свой код и использовать его.Это демонстрирует некоторые из универсальности, представленной с
RecyclerView
использованиемRecyclerView.OnChildAttachStateChangeListener
.Редактировать 2019 год : версия kotlin мной, Java, от Хьюго Виссера, хранится ниже
Котлин / Ява
Создайте файл
values/ids.xml
и поместите в него:затем добавьте код ниже в ваш источник
Котлин
Применение:
(он также поддерживает длительный клик по пункту и смотрите ниже еще одну функцию, которую я добавил)
реализация (моя адаптация к коду Hugo Visser Java):
(см. ниже, вам также нужно добавить файл XML)
Бонусная особенность версии Kotlin
Иногда вы не хотите, чтобы все элементы RecyclerView были кликабельными.
Чтобы справиться с этим, я представил
ItemClickSupportViewHolder
интерфейс, который вы можете использовать на своем устройстве,ViewHolder
чтобы контролировать, какой элемент кликабелен.Пример:
Ява
Применение:
(он также поддерживает длинный элемент)
Реализация (комментарии, добавленные мной):
Как это работает (почему это эффективно)
Этот класс работает, прикрепляя
RecyclerView.OnChildAttachStateChangeListener
кRecyclerView
. Этот слушатель уведомляется каждый раз, когда ребенок присоединяется или отсоединяется отRecyclerView
. Код использует это для добавления прослушивателя касания / длительного щелчка к представлению. Это слушатель спроситьRecyclerView
заRecyclerView.ViewHolder
который содержит позицию.Это более эффективно, чем другие решения, поскольку позволяет избежать создания нескольких прослушивателей для каждого представления и продолжать уничтожать и создавать их во
RecyclerView
время прокрутки.Вы также можете адаптировать код, чтобы вернуть вам самого держателя, если вам нужно больше.
Последнее замечание
Имейте в виду, что ПОЛНОСТЬЮ нормально обрабатывать его в вашем адаптере, установив в каждом представлении списка прослушиватель щелчков, как и в других предложенных ответах.
Это просто не самая эффективная вещь (вы создаете нового слушателя каждый раз, когда повторно используете представление), но это работает, и в большинстве случаев это не проблема.
Это также немного противоречит разделению интересов, потому что на самом деле задача Адаптера не делегировать события щелчка.
источник
addTo()
иremoveFrom()
. Экземпляр связан с тегом recyclerview и умирает вместе с ним или при удалении вручную.onCreateViewHolder
и все.RecyclerView
.Мне нравится этот способ, и я им пользуюсь
внутри
Положил
И создайте этот класс где угодно
Я читал ранее, что есть лучший способ, но мне нравится этот путь легкий и не сложный.
источник
MyOnClickListener
преобразовать в экземплярную переменную, потому что вы будете каждый раз создавать его новый экземпляр сnew
ключевымrecyclerView
в MyOnClickListener?Android Recyclerview С
onItemClickListener
, Почему мы не можем попробовать это работает какListView
только.Источник: Ссылка
И установите это в RecyclerView:
источник
SwipeRefreshLayout
Благодаря @marmor я обновил свой ответ.
Я думаю, что это хорошее решение для обработки onClick () в конструкторе класса ViewHolder и передачи его родительскому классу через интерфейс OnItemClickListener .
MyAdapter.java
Использование адаптера в других классах:
MyFragment.java
источник
onBindViewHolder()
вызывается много раз для одного и того же представления при прокрутке. Даже создание синглаOnClickListener
не поможет, потому что вы будете сбрасыватьOnClickListener
каждый раз, когдаonBindViewHolder()
вызывается. Вместо этого смотрите решение @ MLProgrammer-CiM.MyAdapter.ViewHolder vh = new ViewHolder(v, new MyAdapter.ViewHolder.IMyViewHolderClicks() ....
вы можете создать единого слушателя для всех представлений.Ребята используют этот код в вашей основной деятельности. Очень эффективный метод
Вот ваш класс Адаптер.
После этого вы получите этот метод переопределения в вашей деятельности.
источник
> Чем RecyclerView отличается от Listview?
Отличие заключается в том, что есть
LayoutManager
класс с RecyclerView , с помощью которого вы можете управлятьRecyclerView
как-Как и для горизонтальной прокрутки для RecyclerView-
источник
Вслед за отличным решением RxJava от MLProgrammer-CiM
Потреблять / Наблюдать за кликами
RxJava 2. +
Измените оригинал tl; dr как:
PublishSubject#asObservable()
был удален. Просто верни то,PublishSubject
что естьObservable
.источник
Как собрать воедино пример ...
Типы ViewHolder
источник
Насколько я понимаю ответ MLProgrammer-CiM , просто можно просто сделать это:
источник
Прочитав ответ @ MLProgrammer-CiM , вот мой код:
источник
getAdapterPosition
можете вернуться-1
за «без позиции».Я сделал это очень просто:
Просто добавьте 1 строку для позиции Clicked RecyclerView :
Полный код для класса ViewHolder :
Надеюсь, что это поможет вам.
источник
getAdapterPosition
вместоgetLayoutPosition
. Охранять против-1
.Я использую этот метод для запуска намерения из RecyclerView:
источник
onBindViewHolder(...)
что не вызывается послеnotify()
методов. Таким образом, вы можете получить неправильную позицию щелчка в некоторых ситуациях.RecyclerView не имеет
onItemClickListener
причины, потому что RecyclerView отвечает за повторное использование представлений (удивительно!), Поэтому ответственность за обработку получаемых событий щелчка лежит на представлении.Это на самом деле делает его намного проще в использовании, особенно если у вас есть элементы, которые можно нажимать в нескольких местах.
В любом случае, обнаружение щелчка по элементу RecyclerView очень просто. Все, что вам нужно сделать, это определить интерфейс (если вы не используете Kotlin, в этом случае вы просто передаете лямбду):
Тот же код в Котлине:
То, что вам не нужно делать:
1.) вам не нужно перехватывать сенсорные события вручную
2.) вам не нужно возиться с слушателями изменения состояния вложенного потомка
3.) вам не нужен PublishSubject / PublishRelay из RxJava
Просто используйте слушатель щелчка.
источник
Смотрите мой подход по этому вопросу:
Сначала объявите интерфейс как это:
Затем создайте адаптер:
А теперь давайте посмотрим, как интегрировать это из фрагмента:
источник
Если вы хотите добавить onClick () в дочернее представление элементов, например, кнопку в элементе, я обнаружил, что вы можете легко сделать это в onCreateViewHolder () вашего собственного RecyclerView.Adapter, например, так:
Я не знаю, хороший ли это путь, но он работает хорошо. Если у кого есть идеи получше, очень рад сообщить мне и исправить мой ответ! :)
источник
Вот способ реализовать это довольно легко, если у вас есть список POJO и вы хотите получить его одним щелчком мыши снаружи адаптера.
В вашем адаптере создайте прослушиватель для событий щелчка и метод для его установки:
}
В вашем ViewHolder реализуйте onClickListener и создайте член класса для временного хранения POJO, представляемого представлением, таким образом (это пример, создание сеттера было бы лучше):
Вернувшись в свой адаптер, установите текущий POJO, когда привязан ViewHolder (или равным нулю, если в текущем представлении его нет):
Вот и все, теперь вы можете использовать это так из вашего фрагмента / деятельности:
источник
mMyAdapter.setOnItemClickListener(MyAdapter.OnItemClickListener() {});
Да, ты можешь
источник
Здесь вы можете обрабатывать несколько нажатий, смотрите код ниже, и это очень эффективно
источник
itemView
.Модифицировал мой комментарий ...
источник
getAdapterPosition()
.Отметьте тот, в котором я все правильно реализовал
Класс RecyclerViewHolder
адаптер
Интерфейс
источник
Это сработало для меня:
источник
setOnClickListener(holder)
вonBindViewHolder()
. Потому что onBindViewHolder (...) не вызывается после методов notify (). Таким образом, вы можете получить неправильную позицию щелчка в некоторых ситуациях.onCreateViewHolder
.Перейти на
mainView
изrowLayout(cell)
васRecyclerView
и в вашейOnBindViewHolder
записи этого кода:источник
Вместо реализации интерфейса View.OnClickListener внутри держателя вида или создания и интерфейса и реализации интерфейса в вашей деятельности. Я использовал этот код для простой реализации OnClickListener.
источник
Держатель изнутри
Внутри OnBindViewHolder ()
И дайте мне знать, у вас есть вопрос по поводу этого решения?
источник
onCreateViewHolder
для лучшей производительности, но тогда вам нужно получить позицию, используяgetAdapterPosition()
(и защититься-1
)источник
использовать PlaceHolderView
источник
Я написал библиотеку для обработки события щелчка мышью элемента просмотра Android. Вы можете найти весь учебник в https://github.com/ChathuraHettiarachchi/RecycleClick
или для обработки предмета длительное нажатие вы можете использовать
источник
Анимация recyclerview не была протестирована, другая - нормальная. Я думаю, что это было оптимизировано до максимума. Интерфейс имеет другое использование, вы можете временно игнорировать.
Это интерфейс
Это абстрактный класс
Вам нужно только это
источник
Пример с getTag () / setTag () и слушателем одиночного щелчка для всего адаптера:
TAG_POSITION, определенный в файле tags.xml как
источник