How to create context menu for RecyclerView
Thanks for the info and comments. I was able to achieve ContextMenu
for items in Recyclerview
.
Here is what I did
in Fragment's onViewCreated
method or Activity's 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 the ViewHolder
class implement 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 add OnLongClickListener
on the holder.itemView to capture the position before the context menu is loaded:
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 are no reference issues. (may not be required).
@Overridepublic void onViewRecycled(ViewHolder holder) { holder.itemView.setOnLongClickListener(null); super.onViewRecycled(holder);}
Finally in the Fragment/Activity override the onContextItemSelected
as under:
@Overridepublic 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);}
You can't directly implement these method like onClickListener,OnContextMenuListener etc. because RecycleView extends android.view.ViewGroup. So we cant directly use these method.We can implement these methods in ViewHolder adapter class.We can use context menu in RecycleView like this way:
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 implements the context menu.
@Overridepublic 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 get any difficulties ask in comment.
The current answer is not correct. 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 Fragment (or Activity):
@Overridepublic void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mRecyclerView = view.findViewById(R.id.recyclerview); registerForContextMenu(mRecyclerView);}@Overridepublic 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);}@Overridepublic 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(); }}