Как реализовать контекстное меню для RecyclerView?
Видимо, вызов registerForContextMenu(recyclerView)
не работает. Звоню по фрагменту. Кому-нибудь удалось это реализовать?
android
contextmenu
android-recyclerview
Биной Бабу
источник
источник
Ответы:
Вы не можете напрямую реализовать этот метод, например onClickListener , OnContextMenuListener и т. Д. , Потому что RecycleView расширяет android.view.ViewGroup . Таким образом, мы не можем напрямую использовать этот метод. Мы можем реализовать эти методы в классе адаптера ViewHolder . Мы можем использовать контекстное меню в RecycleView следующим образом:
Теперь мы следуем той же процедуре, пока реализуем контекстное меню.
Если возникнут трудности, спрашивайте в комментариях.
источник
onContextItemSelected
на уровне активности / фрагмента.getTitle
работает,getItemId
работает, ноgetMenuInfo
выдает null. Итак, как получитьViewHolder
?getMenuInfo()
возвращает nullonContextItemSelected()
. Может быть, у людей, которые заставили это работать, естьonCreateContextMenu()
метод в представлении выше по иерархии (RecyclerView
илиFragment
)? Это может сработать, но затем мы перейдем к другим ответам на этот вопрос.menu.add(this.getAdapterPosition(), v.getId(), 0, "Call");
и затем в своем методе обратного вызова test,item.getGroupId()
чтобы получить позициюСпасибо за информацию и комментарии. Мне удалось получить
ContextMenu
товары вRecyclerview
.Вот что я сделал
в
onViewCreated
методе Fragment или ActivityonCreate
:Затем в адаптере добавьте
сделать
ViewHolder
класс реализациейOnCreateContextMenuListener
onBindViewHolder
добавьте методOnLongClickListener
в Holder.itemView для захвата позиции до загрузки контекстного меню:Затем
onViewRecycled
удалите Listener, чтобы не было проблем со ссылками. (может не потребоваться).Наконец, во фрагменте / действии переопределите следующее
onContextItemSelected
:источник
Текущий ответ неверен. Вот рабочая реализация:
В вашем фрагменте (или действии):
И, наконец, в вашем ViewHolder:
источник
getChildPosition()
теперь устарел. Я использовалgetChildAdapterPosition()
вместо этого.getChildPosition()
устарело вcom.android.support:recyclerview-v7:22.0.0
.Попробуйте это для
View
элемента в recycleViewВы можете использовать его с установкой данных для
ViewHolder
элементаисточник
Ответ Прабхакара правильный, но он не объяснил, как получить данные, относящиеся к нажатому элементу, когда выбран элемент контекстного меню. Мы можем использовать
onContextItemSelected
обратный вызов, но в этом случае онContextMenuInfo
недоступен (null
) (еслиgetContextMenuInfo()
метод не переопределен для нажатого представления). Итак, самое простое решение - добавитьOnMenuItemClickListener
прямо вMenuItem
.источник
RecyclerView
только для переопределенияgetContextMenuInfo
и т. Д., Даже если это не так эффективно, как позволить фрагменту / активности обрабатывать щелчки. Слушатели будут иметь доступ к данным в держателе, поэтому вам не понадобится позиция. И теоретически вы можете в любом случае кэшировать позицию после привязки в вашем адаптере и использовать делегирование для вызова из вашего держателя, если это необходимо, хотяContext
иногда может быть достаточно использования from одного из связанных представлений.@ Ответ Рено сработал для меня, но сначала потребовалось несколько исправлений кода. Как будто он опубликовал фрагменты из нескольких разных итераций своего кода. Необходимо внести следующие изменения:
RecyclerContextMenuInfo
иRecyclerViewContextMenuInfo
принадлежат к одному классу. Выберите имя и придерживайтесь его.ViewHolder
Должен реализоватьView.OnLongClickListener
, и не забудьте позвонитьsetOnLongClickListener()
по этому вопросу в конструкторе.onLongClick()
слушателеgetView().showContextMenu()
совершенно не так. Вы должны позвонитьshowContextMenuForChild()
в свойContextMenuRecyclerView
, иначеContextMenuInfo
вы войдетеonCreateContextMenu()
иonContextItemSelected()
будет нулевым.Мой отредактированный код ниже:
ContextMenuRecyclerView:
В вашем фрагменте:
В вашем ViewHolder:
Кроме того , убедитесь , что вы замените
RecyclerView
сContextMenuRecyclerView
в макете!источник
recyclerView.showContextMenuForChild(itemView);
наitemView.showContextMenu()
.Вот простой способ использовать контекст меню в элементах RecyclerView.
Во-первых, вам нужна позиция предмета
В классе адаптера:
В
onBindViewHolder
зацепить пользовательский слушатель:В MainActivity (Activity / Fragment) создайте поле:
В объекте адаптера установите настраиваемый прослушиватель:
Во-вторых, создайте свое меню
В res -> menu Создайте файл, содержащий ваш пункт меню
context_menu_main.xml
:В MainActivity: Реализовать как
onCreateContextMenu
иonContextItemSelected
:В-третьих, вернемся к объекту адаптера
показать контекстное меню.
Дополнительная информация в документации по меню
источник
Вот более простой способ сделать это с помощью Kotlin, который работал у меня. Основная проблема - выяснить положение нажатого элемента. Внутри вашего адаптера вы можете разместить этот фрагмент кода, и он сможет фиксировать положение элемента, для которого отображается контекстное меню; вот и все.
источник
Возможно, я опоздал на вечеринку, но у меня есть рабочее решение . Я изложил суть этого.
Добавить контекстное меню в RecyclerView
ActivityName.java
RecyclerAdapter.java
источник
Я объединил свое решение с решением от @Hardik Shah:
В своей деятельности имею:
В адаптере у меня есть:
Во фрагменте у меня есть:
источник
Привет, ребята, у меня появилась альтернатива. Я просто регистрирую свой itemView с помощью registerContextMenu в конструкторе ViewHolder, а также устанавливаю onLongClikcListener на тот же View. В реализации onLongClick (View v) я просто получаю нажатую позицию с помощью getLayoutPosition () и сохраняю в переменной экземпляра (я создал класс для представления этих данных, точно так же, как ожидается, что ContextMenuInfo будет работать), но более важно сделать обязательно верните false в этом методе. Все, что вам нужно сделать сейчас, это в вас onContextItemSelected (элемент MenuItem), прочитать данные, которые вы храните в своей переменной экземпляра, и, если они действительны, продолжайте свои действия. Вот отрывок.
Я делаю ViewHolder реализацией OnLongClickListener, но вы можете делать это любым удобным для вас способом.
Вы также можете установить это в адаптере или в другом представлении, которое у вас есть в ViewHolder (например, TextView). Важным является реализация onLongClik ().
Самое приятное то, что вы все еще можете обрабатывать событие LongClick, возвращающее true, в тех случаях, когда вы хотите, и conextMenu не отображается.
Этот метод работает, потому что registerForContextView делает View LongClickable, и когда пришло время обработать ContextMenu, система вызывает performLongClick, который сначала вызывает реализацию onLongClick, а если она возвращает false, то вызывает showContextMenu.
источник
Я уже давно использую это решение, и оно мне очень понравилось.
Теперь в вашем фрагменте или Activity реализуйте следующие методы.
Наконец, зарегистрируйтесь в contextMenu на сайте recyclerview.
Это должно сработать!
источник
Вот как вы можете реализовать контекстное меню для RecyclerView и получить позицию элемента, для которого был выбран пункт контекстного меню:
}
источник
Решение для тех, кто хочет получать id товара при звонке
ContextMenu
.Если у вас есть
RecyclerView
такие элементы (содержащие кликабельныеImageView
):тогда вы должны получать обратные вызовы от
onClickListener
.Адаптер
Фрагмент
Предупреждение!
Если вы используете на
ViewPager
основе одного фрагмента (все страницы похожи на списки), вы столкнетесь с проблемой. Когда вы переопределите,onContextItemSelected
чтобы понять, какой пункт меню был выбран, вы получите идентификатор элемента списка с первой страницы! Чтобы решить эту проблему, см. Неправильный фрагмент в ViewPager получает вызов onContextItemSelected .источник
Я боролся с этим, потому что Android не справляется с этим для меня в RecyclerView, который очень хорошо работал для ListView.
Самая сложная часть заключается в том, что часть ContextMenuInfo встроена в представление, которое вы не можете легко прикрепить, кроме как переопределить представление.
Итак, вам понадобится оболочка, которая поможет вам доставить информацию о позиции в Activity.
}
Затем в вашем RecyclerAdapter, когда вы создаете ViewHolders, вам нужно установить Wrapper в качестве корневого представления и зарегистрировать contextMenu для каждого представления.
}
И, наконец, в своей деятельности вы сможете делать то, что обычно делаете:
источник
Лучше всего было использовать контекстное меню с представлением ресайклера, если вы создадите собственное представление ресайклера и переопределите
getContextMenuInfo()
метод и вернете свой собственный экземпляр информационного объекта контекстного меню, чтобы вы могли получать позиции, когда он был создан, и когда меню щелкают:Взгляните на эту суть, которую я создал:
https://gist.github.com/resengupta/2b2e26c949b28f8973e5
источник
Немного расширяя некоторые из приведенных выше ответов, если вы хотите избежать ручного определения меню в своем коде в Adaptor / ViewHolder, вы можете использовать PopupMenu и расширить параметры меню из стандартного файла ресурсов menu.xml.
Пример ниже показывает это, включая возможность передать прослушиватель, который вы можете реализовать в своем фрагменте / действии, чтобы реагировать на щелчки в контекстном меню.
Полный текст здесь https://gist.github.com/brettwold/45039b7f02ce752ae0d32522a8e2ad9c
источник
Вы можете передать OnCreateContextMenuListener в ViewHolder при связывании. Этот слушатель может создавать собственное меню для каждого элемента данных. Просто добавьте setOnCreateContextMenuListener в свой ViewHolder и вызовите его во время привязки.
}
В адаптере:
источник
В моем случае мне пришлось использовать в
onContextItemSelected()
методе данные из моего фрагмента . Решение, к которому я пришел, заключалось в том, чтобы передать экземпляр фрагмента в мой адаптер и зарегистрировать элемент представления в держателе представления:Затем
onCreateContextMenu()
вы можете сохранить индекс в локальной переменной:selectedViewIndex = (int)v.getTag();
и получить его в
onContextItemSelected()
источник
В первый раз, когда я столкнулся с этой проблемой с обычными адаптерами, я создал свой собственный подкласс View и сохранил в нем все, что мне было нужно. Мне действительно не понравилось это решение, я потратил много времени на рассмотрение замечательных идей, которые предлагали люди, и решил, что они мне не нравятся больше. Так что я как бы собрал все воедино, некоторое время потряс и выпустил что-то новое, что мне нравится.
Начнем с пары служебных классов. ContextMenuHandler - это интерфейс для любого объекта, который будет обрабатывать контекстное меню. На практике это будет подкласс ViewHolder, но теоретически это может быть что угодно.
Далее следует интерфейс, который должен быть реализован любым представлением, которое будет использоваться как непосредственный дочерний элемент RecyclerView.
Далее, любое представление, которое будет создавать контекстное меню в качестве дочернего элемента RecylcerView, должно реализовать ViewWIthContextMenu. В моем случае мне нужен был только подкласс LinearLayout.
И, наконец, нам нужен усиленный класс Fragment, чтобы перехватывать вызовы контекстного меню и перенаправлять их соответствующему обработчику.
После всего этого окончательная реализация довольно проста. Основной фрагмент должен быть подклассом FragmentWithContextMenu. Он обычно устанавливает основное окно RecylerWindow и передает себя подклассу Adapter. Подкласс адаптера выглядит так
Вот и все. Вроде все работает. Он поместил все служебные классы в отдельный пакет contextmenu, чтобы я мог дать имена классов, которые соответствуют классам, которые там подклассы, но я подумал, что это будет более запутанно.
источник
Хорошо, исходя из ответа @ Flexo, я приведу mPosition в порядок ...
затем в onContextItemSelected я использую
И все работает нормально, я легко получаю позицию массива
источник