How to create a context menu for RecyclerView

How to implement a context menu for RecyclerView? Apparently, calling registerForContextMenu(recyclerView) not working. I call it a fragment. Has anyone been successful in this?

+81
android contextmenu android-recyclerview
Oct. 20 '14 at 13:30
source share
22 answers

You cannot directly implement these methods such as onClickListener , OnContextMenuListener , etc., because RecycleView extends android.view.ViewGroup . Therefore, we cannot directly use this method. We can implement these methods in the ViewHolder adapter class . We can use the context menu in RecycleView as follows:

 public static class ViewHolder extends RecyclerView.ViewHolder implements OnCreateContextMenuListener { TextView tvTitle; ImageView ivImage; public ViewHolder(View v) { super(v); tvTitle =(TextView)v.findViewById(R.id.item_title); v.setOnCreateContextMenuListener(this); } 

Now we follow the same procedure, while we implement the context menu.

 @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { menu.setHeaderTitle("Select The Action"); menu.add(0, v.getId(), 0, "Call");//groupId, itemId, order, title menu.add(0, v.getId(), 0, "SMS"); } 

If you have any difficulties, ask in the comments.

+78
Jan 03 '15 at 8:13
source share

Thanks for the info and comments. I was able to reach ContextMenu for elements in Recyclerview .

Here is what i did

in the onViewCreated Fragment onViewCreated or Activity onCreate method:

 registerForContextMenu(mRecyclerView); 

Then in Adapter add

 private int position; public int getPosition() { return position; } public void setPosition(int position) { this.position = position; } 

make an implementation of the ViewHolder class OnCreateContextMenuListener

 public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener { public ImageView icon; public TextView fileName; public ImageButton menuButton; public ViewHolder(View v) { super(v); icon = (ImageView)v.findViewById(R.id.file_icon); fileName = (TextView)v.findViewById(R.id.file_name); menuButton = (ImageButton)v.findViewById(R.id.menu_button); v.setOnCreateContextMenuListener(this); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { //menuInfo is null menu.add(Menu.NONE, R.id.ctx_menu_remove_backup, Menu.NONE, R.string.remove_backup); menu.add(Menu.NONE, R.id.ctx_menu_restore_backup, Menu.NONE, R.string.restore_backup); } } 

onBindViewHolder method adds OnLongClickListener to OnLongClickListener file to capture position before loading context menu:

 holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { setPosition(holder.getPosition()); return false; } }); 

Then in onViewRecycled remove the listener so that there is no problem with the link. (may not be required).

 @Override public void onViewRecycled(ViewHolder holder) { holder.itemView.setOnLongClickListener(null); super.onViewRecycled(holder); } 

Finally, in Fragment / Activity, override onContextItemSelected , as shown below:

 @Override public boolean onContextItemSelected(MenuItem item) { int position = -1; try { position = ((BackupRestoreListAdapter)getAdapter()).getPosition(); } catch (Exception e) { Log.d(TAG, e.getLocalizedMessage(), e); return super.onContextItemSelected(item); } switch (item.getItemId()) { case R.id.ctx_menu_remove_backup: // do your stuff break; case R.id.ctx_menu_restore_backup: // do your stuff break; } return super.onContextItemSelected(item); } 
+82
Jan 11 '15 at 11:20
source share

The current answer is incorrect. Here's a working implementation:

 public class ContextMenuRecyclerView extends RecyclerView { private RecyclerViewContextMenuInfo mContextMenuInfo; @Override protected ContextMenu.ContextMenuInfo getContextMenuInfo() { return mContextMenuInfo; } @Override public boolean showContextMenuForChild(View originalView) { final int longPressPosition = getChildPosition(originalView); if (longPressPosition >= 0) { final long longPressId = getAdapter().getItemId(longPressPosition); mContextMenuInfo = new RecyclerViewContextMenuInfo(longPressPosition, longPressId); return super.showContextMenuForChild(originalView); } return false; } public static class RecyclerViewContextMenuInfo implements ContextMenu.ContextMenuInfo { public RecyclerViewContextMenuInfo(int position, long id) { this.position = position; this.id = id; } final public int position; final public long id; } } 

In your snippet (or action):

 @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mRecyclerView = view.findViewById(R.id.recyclerview); registerForContextMenu(mRecyclerView); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); // inflate menu MenuInflater inflater = getActivity().getMenuInflater(); inflater.inflate(R.menu.my_context_menu, menu); } @Override public boolean onContextItemSelected(MenuItem item) { return super.onContextItemSelected(item); RecyclerViewContextMenuInfo info = (RecyclerViewContextMenuInfo) item.getMenuInfo(); // handle menu item here } 

And finally, in your ViewHolder:

 class MyViewHolder extends RecyclerView.View.ViewHolder { ... private void onLongClick() { itemView.showContextMenu(); } } 
+23
Apr 23 '15 at 13:59 on
source share

Try this for the View element in recycleView

 .setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { menu.add("delete").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { //do what u want return true; } }); } }); 

You can use it with data customization in the ViewHolder element

+19
Nov 11 '15 at 13:35
source share

Prabhakar's answer is correct, but he did not explain how to get the data associated with the clicked item when the context menu item is selected. We can use the onContextItemSelected , but ContextMenuInfo not available ( null ) in this case (if the getContextMenuInfo() method is not redefined for the pressed view). So, the easiest solution is to add OnMenuItemClickListener directly to MenuItem .

 private class ViewHolder extends RecyclerView.ViewHolder { private final TextView mTitleTextView; private MyItemData mData; public ViewHolder(View view) { super(view); mTitleTextView = (TextView)view.findViewById(R.id.title); view.setOnCreateContextMenuListener(mOnCreateContextMenuListener); } public void bind(@NonNull MyItemData data) { mData = data; String title = mData.getTitle(); mTitleTextView.setText(title); } private final View.OnCreateContextMenuListener mOnCreateContextMenuListener = new View.OnCreateContextMenuListener() { @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { if (mData!= null) { MenuItem myActionItem = menu.add("My Context Action"); myActionItem.setOnMenuItemClickListener(mOnMyActionClickListener); } } }; private final MenuItem.OnMenuItemClickListener mOnMyActionClickListener = new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { //todo: process item click, mData is available here!!! return true; } }; } 
+14
Oct 16 '15 at 21:38
source share
Answer to

@Renaud worked for me, but first required a few code fixes. As if he posted snippets from several different iterations of his code. The changes to be made are as follows:

  • RecyclerContextMenuInfo and RecyclerViewContextMenuInfo are the same class. Choose a name and stick to it.
  • ViewHolder should implement View.OnLongClickListener and don't forget to call setOnLongClickListener() on the element in the constructor.
  • In the onLongClick() getView().showContextMenu() completely wrong. You must call showContextMenuForChild() in ContextMenuRecyclerView , otherwise the ContextMenuInfo that you get in onCreateContextMenu() and onContextItemSelected() will be null.

My edited code is below:

ContextMenuRecyclerView:

 public class ContextMenuRecyclerView extends RecyclerView { private RecyclerViewContextMenuInfo mContextMenuInfo; @Override protected ContextMenu.ContextMenuInfo getContextMenuInfo() { return mContextMenuInfo; } @Override public boolean showContextMenuForChild(View originalView) { final int longPressPosition = getChildPosition(originalView); if (longPressPosition >= 0) { final long longPressId = getAdapter().getItemId(longPressPosition); mContextMenuInfo = new RecyclerViewContextMenuInfo(longPressPosition, longPressId); return super.showContextMenuForChild(originalView); } return false; } public static class RecyclerViewContextMenuInfo implements ContextMenu.ContextMenuInfo { public RecyclerViewContextMenuInfo(int position, long id) { this.position = position; this.id = id; } final public int position; final public long id; } } 

In your snippet:

 @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mRecyclerView = view.findViewById(R.id.recyclerview); registerForContextMenu(mRecyclerView); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); // inflate menu here // If you want the position of the item for which we're creating the context menu (perhaps to add a header or something): int itemIndex = ((ContextMenuRecyclerView.RecyclerViewContextMenuInfo) menuInfo).position; } @Override public boolean onContextItemSelected(MenuItem item) { ContextMenuRecyclerView.RecyclerViewContextMenuInfo info = (ContextMenuRecyclerView.RecyclerViewContextMenuInfo) item.getMenuInfo(); // handle menu here - get item index or ID from info return super.onContextItemSelected(item); } 

In your ViewHolder:

 class MyViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener { public MyViewHolder( View itemView ) { super( itemView ); itemView.setOnLongClickListener( this ); } @Override public boolean onLongClick() { recyclerView.showContextMenuForChild( v ); return true; } } 

Also, make sure you replace RecyclerView with ContextMenuRecyclerView in your layout!

+10
Sep 17 '15 at 14:34
source share

I combined my solution with a solution from @Hardik Shah:

In my activity:

 @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); if (v.getId() == R.id.rvQuests) { getMenuInflater().inflate(R.menu.list_menu, menu); } } 

In the adapter, I have:

 private MainActivity context; private int position; public int getPosition() { return position; } public void setPosition(int position) { this.position = position; } public QuestsAdapter(MainActivity context, List<Quest> objects) { this.context = context; this.quests.addAll(objects); } public class QuestViewHolder extends RecyclerView.ViewHolder { private QuestItemBinding questItemBinding; public QuestViewHolder(View v) { super(v); questItemBinding = DataBindingUtil.bind(v); v.setOnCreateContextMenuListener(context); } } @Override public void onBindViewHolder(final QuestViewHolder holder, int position) { Quest quest = quests.get(position); holder.questItemBinding.setQuest(quest); holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { setPosition(holder.getAdapterPosition()); return false; } }); } @Override public void onViewRecycled(QuestViewHolder holder) { holder.itemView.setOnLongClickListener(null); super.onViewRecycled(holder); } 

In the fragment I:

 @Override public boolean onContextItemSelected(MenuItem item) { int position = ((QuestsAdapter) questsList.getAdapter()).getPosition(); switch (item.getItemId()) { case R.id.menu_delete: Quest quest = questsAdapter.getItem(position); App.getQuestManager().deleteQuest(quest); questsAdapter.remove(quest); checkEmptyList(); return true; default: return super.onContextItemSelected(item); } } 
+3
May 16 '16 at 13:08
source share

Maybe I'm late for the party, but I have a working solution . I made the point for him.

Add context menu to RecyclerView

ActivityName.java

 //Import Statements public class ActivityName extends AppCompatActivity { private RecyclerView mRecyclerView; private RecyclerView.Adapter mAdapter; private RecyclerView.LayoutManager mLayoutManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view_birthdays); //Recycle View mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); mLayoutManager = new LinearLayoutManager(getApplicationContext()); mRecyclerView.setLayoutManager(mLayoutManager); mAdapter = new BirthdaysListAdapter(data, this); mRecyclerView.setAdapter(mAdapter); } 

RecyclerAdapter.java

 //Import Statements public class BirthdaysListAdapter extends RecyclerView.Adapter<BirthdaysListAdapter.ViewHolder> { static Context ctx; private List<typeOfData> Data; public BirthdaysListAdapter(List<typeOfData> list, Context context) { Data = list; this.ctx = context; } BirthdaysListAdapter() { } public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener { public TextView name; public TextView Birthday; public ImageView colorAlphabet; public TextView textInImg; public ViewHolder(View v) { super(v); name = (TextView) v.findViewById(R.id.name); Birthday = (TextView) v.findViewById(R.id.Birthday); colorAlphabet = (ImageView) v.findViewById(R.id.colorAlphabet); textInImg = (TextView) v.findViewById(R.id.textInImg); v.setOnCreateContextMenuListener(this); //REGISTER ONCREATE MENU LISTENER } @Override public void onCreateContextMenu(ContextMenu menu, View v //CREATE MENU BY THIS METHOD ContextMenu.ContextMenuInfo menuInfo) { new BirthdaysListAdapter().info = (AdapterView.AdapterContextMenuInfo) menuInfo; MenuItem Edit = menu.add(Menu.NONE, 1, 1, "Edit"); MenuItem Delete = menu.add(Menu.NONE, 2, 2, "Delete"); Edit.setOnMenuItemClickListener(onEditMenu); Delete.setOnMenuItemClickListener(onEditMenu); } //ADD AN ONMENUITEM LISTENER TO EXECUTE COMMANDS ONCLICK OF CONTEXT MENU TASK private final MenuItem.OnMenuItemClickListener onEditMenu = new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { DBHandler dbHandler = new DBHandler(ctx); List<WishMen> data = dbHandler.getWishmen(); switch (item.getItemId()) { case 1: //Do stuff break; case 2: //Do stuff break; } return true; } }; } public List<ViewBirthdayModel> getData() { return Data; } @Override public long getItemId(int position) { return super.getItemId(position); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_view_birthdays, parent, false); ViewHolder vh = new ViewHolder(view); return vh; } @Override public void onBindViewHolder(final ViewHolder holder, int position) { holder.name.setText(Data.get(position).getMan().getName()); holder.Birthday.setText(Data.get(position).getMan().getBday()); holder.colorAlphabet.setBackgroundColor(Color.parseColor(Data.get(position).getColor())); holder.textInImg.setText(String.valueOf(Data.get(position).getMan().getName().toUpperCase().charAt(0))); } @Override public int getItemCount() { return Data.size(); } private int position; public int getPosition() { return position; } public void setPosition(int position) { this.position = position; } } 
+2
Jul 17 '16 at 7:58
source share

Here's an easy way to use menu context in RecyclerView items

First, you need a position position

In adapter class:

  /** * Custom on long click item listener. */ onLongItemClickListener mOnLongItemClickListener; public void setOnLongItemClickListener(onLongItemClickListener onLongItemClickListener) { mOnLongItemClickListener = onLongItemClickListener; } public interface onLongItemClickListener { void ItemLongClicked(View v, int position); } 

In onBindViewHolder , a user listener is connected:

  // Hook our custom on long click item listener to the item view. holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { if (mOnLongItemClickListener != null) { mOnLongItemClickListener.ItemLongClicked(v, position); } return true; } }); 

In MainActivity (Activity / Fragment) create a field:

 private int mCurrentItemPosition; 

In the Adapter object, set a custom listener:

  mAdapter.setOnLongItemClickListener(new FileAdapter.onLongItemClickListener() { @Override public void ItemLongClicked(View v, int position) { mCurrentItemPosition = position; } }); 

Now you have a delicious position for any item that you have been pressing for a long time 😋

Secondly, create your own menu.

In res → menu Create a file for your menu item context_menu_main.xml :

 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/delete" android:title="Delete"/> <item android:id="@+id/share" android:title="Share"/> </menu> 

In MainActivity: do both onCreateContextMenu and onContextItemSelected :

 @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.context_menu_main, menu); } @Override public boolean onContextItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.delete) { } if (id == R.id.share) { } return true; } 

Third, back to your adapter

  1. Register your context menu.
  2. show the context menu.

     registerForContextMenu(mRecyclerView); mAdapter.setOnLongItemClickListener(new FileAdapter.onLongItemClickListener() { @Override public void ItemLongClicked(View v, int position) { mCurrentItemPosition = position; v.showContextMenu(); } }); 

I hope I don’t forget anything 🤔

Further information in the menu documentation

+2
Oct 06 '18 at 18:44
source share

Hi guys, came out with one alternative that works for me. I simply register the itemView with registerContextMenu y ViewHolder Constructor, also setting the onLongClikcListener to the same view. In the onLongClick (View v) implementation, I just get the clicked position using getLayoutPosition () and save it in an instance variable (I created a class to represent this data, ContextMenuInfo is expected to work), but more importantly, be sure to return false in this method. All you need to do now is in you on onContextItemSelected (MenuItem element), read the data that you store in your instance variable, and if it is valid, you do your actions. Here is a fragment.

  public MyViewHolder(View itemView){ super(itemView); registerForContextMenu(itemView); itemView.setOnLongClickListener(this); } 

I am making ViewHolder implementing OnLongClickListener, but you can do it in any way you prefer.

 @Override public boolean onLongClick(View v){ mCurrentLongItem = new ListItemInfo(v.getId(), getLayoutPosition()); return false; // REMEMBER TO RETURN FALSE. } 

You can also set this in the adapter or in another view that you see in the ViewHolder (i.e. TextView). Important is the implementation of onLongClik ().

 @Override public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()){ case R.id.client_edit_context_menu: if(mCurrentLongItem != null){ int position = mCurrentLongItem.position; //TAKE SOME ACTIONS. mCurrentLongItem = null; } return true; } return super.onContextItemSelected(item); } 

The best part is that you can still handle the LongClick event returning true when you want, and conextMenu will not appear.

This method works because registerForContextView creates a View LongClickable, and when ContextMenu processes it, the system calls performLongClick, which first calls the implementation of onLongClick, and if it returns false, then it calls showContextMenu.

+1
Jun 05 '16 at 9:07 on
source share

I have been using this solution for a while and it worked fine for me.

 public class CUSTOMVIEWNAME extends RecyclerView { public CUSTOMVIEWNAME(Context context) { super(context); } public CUSTOMVIEWNAME (Context context, AttributeSet attrs) { super(context, attrs); } public CUSTOMVIEWNAME (Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } private RecyclerContextMenuInfo mContextMenuInfo; @Override protected ContextMenu.ContextMenuInfo getContextMenuInfo() { return mContextMenuInfo; } @Override public boolean showContextMenuForChild(View originalView) { final int longPressPosition = getChildAdapterPosition(originalView); if (longPressPosition >= 0) { final long longPressId = getAdapter().getItemId(longPressPosition); mContextMenuInfo = new RecyclerContextMenuInfo(longPressPosition, ` longPressId); return super.showContextMenuForChild(originalView); } return false; } public class RecyclerContextMenuInfo implements ContextMenu.ContextMenuInfo { public RecyclerContextMenuInfo(int position, long id) { this.position = position; this.id = id; } final public int position; final public long id; } } 

Now in your fragment or Activity we implement the following methods.

  @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); // Inflate Menu from xml resource MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.context_menu, menu); } @Override public boolean onContextItemSelected(MenuItem item) { ContextMenuRecyclerView.RecyclerContextMenuInfo info = (ContextMenuRecyclerView.RecyclerContextMenuInfo) item.getMenuInfo(); Toast.makeText(InstanceOfContext , " User selected " + info.position, Toast.LENGTH_LONG).show(); return false; } 

Finally sign up for context Menu on recyclerview

  //for showing a popup on LongClick of items in recycler. registerForContextMenu(recyclerView); 

That should work!

+1
Mar 19 '17 at 11:15
source share

Here's an easier way to do this with Kotlin, who worked for me. The main problem is determining the position of the item that was clicked. Inside the adapter, you can place this piece of code, and it will be able to capture the position of the element for which the context menu is displayed; all this.

 override fun onBindViewHolder(holder: YourViewHolder, position: Int) { ... holder.view.setOnCreateContextMenuListener { contextMenu, _, _ -> contextMenu.add("Add").setOnMenuItemClickListener { longToast("I'm pressed for the item at position => $position") true } } } 
+1
Nov 20 '18 at
source share

It was best to use a context menu with a recycler view if you create a custom recycler view and override the getContextMenuInfo() method and return your own instance of the context menu information object so that you can get the positions when they were created and when the menu:

 @Override protected ContextMenu.ContextMenuInfo getContextMenuInfo() { return mContextMenuInfo; } 

Look at this gist that I created:

https://gist.github.com/resengupta/2b2e26c949b28f8973e5

0
Mar 26 '15 at 14:22
source share

I fought for this because Android cannot handle this for me in RecyclerView, which works great for ListView.

The hardest part is that part of ContextMenuInfo is built into the view, which you cannot easily attach, except overriding the view.

Therefore, you will need a wrapper to help you deliver position information in Activity.

 public class RecyclerContextMenuInfoWrapperView extends FrameLayout { private RecyclerView.ViewHolder mHolder; private final View mView; public RecyclerContextMenuInfoWrapperView(View view) { super(view.getContext()); setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); mView = view; addView(mView); } public void setHolder(RecyclerView.ViewHolder holder) { mHolder = holder; } @Override protected ContextMenu.ContextMenuInfo getContextMenuInfo() { return new RecyclerContextMenuInfo(mHolder.getPosition(), mHolder.getItemId()); } public static class RecyclerContextMenuInfo implements ContextMenu.ContextMenuInfo { public RecyclerContextMenuInfo(int position, long id) { this.position = position; this.id = id; } final public int position; final public long id; } 

}

Then in your RecyclerAdapter, when you create the ViewHolders, you need to set Wrapper as the root view and register contextMenu in each view.

 public static class AdapterViewHolder extends RecyclerView.ViewHolder { public AdapterViewHolder( View originalView) { super(new RecyclerContextMenuInfoWrapperView(originalView); ((RecyclerContextMenuInfoWrapperView)itemView).setHolder(this); yourActivity.registerForContextMenu(itemView); itemView.setOnCreateContextMenuListener(yourListener); } 

}

And finally, in your activity you will be able to do what you usually do:

 @Override public boolean onContextItemSelected(MenuItem item) { int position = ((RecyclerContextMenuInfoWrapperView.RecyclerContextMenuInfo)item.getMenuInfo()).position; // do whatever you need as now you have access to position and id and everything 
0
Apr 29 '15 at 21:30
source share

Turning around some of the answers above, if you don’t want to manually define the menu in your code in the Adapter / ViewHolder, you can use PopupMenu and inflate the menu options from the standard menu.xml resource file.

Below is an example that includes the ability to convey to the listener, which you can implement in your fragment / event in order to respond to clicks on the context menu.

 public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> { private List<CustomObject> objects; private OnItemSelectedListener listener; private final boolean withContextMenu; class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnCreateContextMenuListener, PopupMenu.OnMenuItemClickListener { @BindView(R.id.custom_name) TextView name; @BindView(R.id.custom_value) TextView value; ViewHolder(View view) { super(view); ButterKnife.bind(this, view); view.setOnClickListener(this); if (withContextMenu) { view.setOnCreateContextMenuListener(this); } } @Override public void onClick(View v) { int position = getAdapterPosition(); if (listener != null) { listener.onCustomerSelected(objects.get(position)); } } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { PopupMenu popup = new PopupMenu(v.getContext(), v); popup.getMenuInflater().inflate(R.menu.custom_menu, popup.getMenu()); popup.setOnMenuItemClickListener(this); popup.show(); } @Override public boolean onMenuItemClick(MenuItem item) { if (listener != null) { CustomObject object = objects.get(getAdapterPosition()); listener.onCustomerMenuAction(object, item); } return false; } } public CustomerAdapter(List<CustomObject> objects, OnItemSelectedListener listener, boolean withContextMenu) { this.listener = listener; this.objects = objects; this.withContextMenu = withContextMenu; } public interface OnItemSelectedListener { void onSelected(CustomObject object); void onMenuAction(CustomObject object, MenuItem item); } @Override public CustomerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.snippet_custom_object_line, parent, false); return new ViewHolder(v); } @Override public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) { CustomObject object = objects.get(position); holder.name.setText(object.getName()); holder.value.setText(object.getValue()); } @Override public int getItemCount() { return objects.size(); } } 

https://gist.github.com/brettwold/45039b7f02ce752ae0d32522a8e2ad9c

0
26 '17 10:05
source share

OnCreateContextMenuListener ViewHolder bind. . setOnCreateContextMenuListener ViewHolder .

  public static class ItemViewHolder extends RecyclerView.ViewHolder { public ItemViewHolder(View itemView) { super(itemView); } void setOnCreateContextMenuListener(View.OnCreateContextMenuListener listener) { itemView.setOnCreateContextMenuListener(listener); } 

}

:

  @Override public void onBindViewHolder(ItemViewHolder viewHolder, int position) { final MyObject myObject = mData.get(position); viewHolder.setOnCreateContextMenuListener(new OnCreateContextMenuListener(){ @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { switch (myObject.getMenuVariant() { case MNU_VARIANT_1: menu.add(Menu.NONE, CTX_MNU_1, Menu.NONE,R.string.ctx_menu_item_1); menu.add(Menu.NONE, CTX_MNU_2,Menu.NONE, R.string.ctx_menu_item_2); break; case MNU_VARIANT_2: menu.add(Menu.NONE, CTX_MNU_3,Menu.NONE, R.string.ctx_menu_item_3); break; default: menu.add(Menu.NONE, CTX_MNU_4, Menu.NONE, R.string.ctx_menu_item_4); } } }); } 
0
31 '17 11:34
source share

onContextItemSelected() . , , , :

 @Override public void onBindViewHolder(final MyListAdapter.ViewHolder viewHolder, int position) { final Object rowObject = myListItems.get(position); // Do your data binding here viewHolder.itemView.setTag(position); fragment.registerForContextMenu(viewHolder.itemView); } 

onCreateContextMenu() :

selectedViewIndex = (int)v.getTag();

onContextItemSelected()

0
09 . '17 23:28
source share

, , View , . , , , , . , - , .

. ContextMenuHandler - , . ViewHolder,

 /** * Interface for objects that wish to create and handle selections from a context * menu associated with a view */ public interface ContextMenuHandler extends View.OnCreateContextMenuListener { boolean onContextItemSelected(MenuItem item); } 

, , RecyclerView.

 public interface ViewWithContextMenu { public void setContextMenuHandler(FragmentWithContextMenu fragment, ContextMenuHandler handler); public ContextMenuHandler getContextMenuHandler(); } 

, , RecylcerView, ViewWIthContextMenu. LinearLayout.

 public class LinearLayoutWithContextMenu extends LinearLayout implements ViewWithContextMenu { public LinearLayoutWithContextMenu(Context context) { super(context); } public LinearLayoutWithContextMenu(Context context, AttributeSet attrs) { super(context, attrs); } private ContextMenuHandler handler; @Override public void setContextMenuHandler(FragmentWithContextMenu fragment, ContextMenuHandler handler) { this.handler = handler; setOnCreateContextMenuListener(fragment); } @Override public ContextMenuHandler getContextMenuHandler() { return handler; } } 

, , Fragment, .

 public class FragmentWithContextMenu extends Fragment { ContextMenuHandler handler = null; @Override public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, view, menuInfo); handler = null; if (view instanceof ViewWithContextMenu) { handler = ((ViewWithContextMenu)view).getContextMenuHandler(); if (handler != null) handler.onCreateContextMenu(menu, view, menuInfo); } } @Override public boolean onContextItemSelected(MenuItem item) { if (handler != null) { if (handler.onContextItemSelected(item)) return true; } return super.onContextItemSelected(item); } } 

. FragmentWithContextMenu. RecylerWindow Adapter. Adapter :

 public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> { private final FragmentWithContextMenu fragment; Adapter(FragmentWithContextMenu fragment) { this.fragment = fragment; } @Override public Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(context) .inflate(R.layout.child_view, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(final Adapter.ViewHolder holder, int position) { // Logic needed to bind holder to specific position // ...... } @Override public int getItemCount() { // Logic to return current item count // .... } public class ViewHolder extends RecyclerView.ViewHolder implements ContextMenuHandler { ViewHolder(View view) { super(view); ((ViewWithContextMenu)view).setContextMenuHandler(fragment, this); view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Do stuff to handle simple clicks on child views // ....... } }); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { // Logic to set up context menu goes here // .... } @Override public boolean onContextItemSelected(MenuItem item) { // Logic to handle context menu item selections goes here // .... return true; } } } 

. , . contextmenu, , , , , .

0
01 '18 6:21
source share

RecyclerView , :

 public class YourAdapter extends RecyclerView.Adapter<YourAdapter.ViewHolder> { ... @Override public void onBindViewHolder(@NonNull final ViewHolder viewHolder, int position) { ... viewHolder.itemView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { menu.add(0, R.id.mi_context_disable, 0, R.string.text_disable) .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { // can do something with item at position given below, // viewHolder is final viewHolder.getAdapterPosition(); return true; } }); menu.add(0, R.id.mi_context_remove, 1, R.string.text_remove) .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { // can do something with item at position given below, // viewHolder is final viewHolder.getAdapterPosition(); return true; } }); } }); } static class ViewHolder extends RecyclerView.ViewHolder { private View itemView; private ViewHolder(@NonNull View itemView) { super(itemView); this.itemView = itemView; } } 

}

0
26 . '18 15:27
source share

, ContextMenu .

RecyclerView ( ImageView ):

list

onClickListener .

 class YourAdapter(private val contextMenuCallback: ContextMenuCallback) : RecyclerView.Adapter<YourAdapter.ViewHolder>() { private var items: MutableList<Item> = mutableListOf() ... override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { val item = items[position] as Item updateItem(viewHolder, item) setOnClickListener(viewHolder.itemView, items[position].id, items[position].title) } private fun setOnClickListener(view: View, id: Int, title: String) { // view.setOnClickListener { v -> } // A click listener for ImageView 'more'. view.more.setOnClickListener { // Here we pass item id, title, etc. to Fragment. contextMenuCallback.onContextMenuClick(view, id, title) } } class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val titleTextView: TextView = itemView.title } class Item( val id: Int, val title: String ) interface ContextMenuCallback { fun onContextMenuClick(view: View, id: Int, title: String) } } 

 class YourFragment : Fragment(), YourAdapter.ContextMenuCallback { private var adapter: YourAdapter? = null private var linearLayoutManager: LinearLayoutManager? = null private var selectedItemId: Int = -1 private lateinit var selectedItemTitle: String override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) adapter = YourAdapter(this) view.recycler_view.apply { layoutManager = linearLayoutManager adapter = this@YourFragment.adapter setHasFixedSize(true) } registerForContextMenu(view.recycler_view) } override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) { activity?.menuInflater?.inflate(R.menu.menu_yours, menu) } override fun onContextItemSelected(item: MenuItem?): Boolean { super.onContextItemSelected(item) when (item?.itemId) { R.id.action_your -> yourAction(selectedItemId, selectedItemTitle) ... } return true } override fun onContextMenuClick(view: View, id: Int, title: String) { // Here we accept item id, title from adapter and show context menu. selectedItemId = id selectedItemTitle = title view.showContextMenu() } } 

Warning!

ViewPager ( ), . onContextItemSelected , , ! , . ViewPager onContextItemSelected .

0
14 . '19 10:55
source share

, @Flexo, mPosition ...

 protected class ExampleViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener { int mPosition; public KWViewHolder(View itemView) { super(itemView); itemView.setOnCreateContextMenuListener(this); } public void setPosition(int position) { mPosition = position; } @Override public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) { contextMenu.setHeaderTitle(R.string.menu_title_context); contextMenu.add(0, R.id.menu_delete, mPosition, R.string.delete); } } 

onContextItemSelected

 item.getOrder() 

,

-one
11 . '16 9:31
source share

It seemed to me that this solution is simpler, I first add OnCreateContextMenuListener to the ViewHolder adapter in recyclerView. As below:

 public class RyViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener { private TextView mView; public MyViewHolder(@NonNull View v) { super(v); mView = v.findViewById(R.id.view); v.setOnCreateContextMenuListener(this); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { mActivity.getMenuInflater().inflate(R.menu.ry_menu, menu); } } 

And then for the fragment or Activity, I override onContextItemSelected, as shown below:

 @Override public boolean onContextItemSelected(MenuItem item) { if (item.getItemId() == R.id.item_i) { Toast.makeText(getApplicationContext(), "Item 1 clicked", Toast.LENGTH_LONG).show(); } return super.onContextItemSelected(item); } 
-one
Nov 27 '18 at 9:53
source share



All Articles