3

I've try to setup a ContextMenu for my RecyclerView when i do a longClick this work perfectly but when i tried to access at getMenuInfo his always null even in the onCreateContextMenu

i have already try this link :

For the registerForContextMenu in the MainActivity:

@Bind(R.id.rvFeed)
RecyclerView         feed;
------
feed.setAdapter(adapter);
registerForContextMenu(feed);

My onCreateContextMenu implementation:

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
    if (info == null) {
        Log.d(TAG, "info == null");
    }
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu_drawer, menu);
}

And the onContextItemSelected :

@Override
public boolean onContextItemSelected(MenuItem item) {
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
    if (info == null) {
        Log.d(TAG, "info == null");
    }
    return super.onContextItemSelected(item);
}

main_menu_drawer :

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_drawer_delete"
        android:title="@string/menufeed_menu_asread" />
</menu>
Community
  • 1
  • 1
florian-do
  • 865
  • 1
  • 13
  • 27

2 Answers2

2

What dark_escape suggested did not work exaclty for my case, but as he suggested getAdapterPosition() can work, and did perfectly for me. Here an example how I used it for a filemanager for deleting. (Following up on his idea that he just asumed that the menueinfo is being needed to remove items or get info from the items)

In the ViewHolder extending View.OnCreateContextMenuListener we override:

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    menu.setHeaderTitle("Select The Action");

    int indexOfItemClickedInList = getAdapterPosition();

    menu.add(0, indexOfItemClickedInList, 0, R.string.ContextMenuItemTitleTextDELETE);
    // keep adding menu items with that AdapterPosition
    // if u need it for the selected actions
}

Ive created the MasterDetail from the template in AndroidStuido. Thus my ViewHolder is declared in a SimpleItemRecyclerViewAdapter and the Adapter is declared in an Activity where I now override this:

@Override
public boolean onContextItemSelected(MenuItem item) {
    int itemid = item.getItemId(); // index of Item clicked in the List
    String title = item.getTitle().toString(); // contextmenu choice text

    // Here I use ifs on the title to see wich item has been chosen
    if (title.equals(getApplicationContext().getResources().getString(R.string.ContextMenuItemTitleTextDELETE))) {
        // Do things that require the item id - like moving photos...
        // in this case I needed it to delete files
        String fnameToDelete = DummyContent.ITEMS.get(itemid).fname;
        MyStaticIOHelperClass.DeleteFileFromDisk(fnameToDelete , this);

        // After actually removing the file 
        // I needed to cleanup the Data used by the recycler
        DummyContent.ITEM_MAP.remove(DummyContent.ITEMS.get(itemid).fname);
        DummyContent.ITEMS.remove(itemid);

        // Rebuild the recycler view after this 
        // I basically call .setAdapter() on the recycler view in there
        // creating the adapter new like I do in onCreate of this Activity
        BuildRecycler();
    }
}


private void BuildRecycler(){
    View recyclerView = findViewById(R.id.trail_list);
    assert recyclerView != null;
    setupRecyclerView((RecyclerView) recyclerView);
}

DummyContent is a static class provided by the Template. It holds/builds Data that is used to fill the recycler view.

t0b4cc0
  • 319
  • 4
  • 19
1

From your question, I understand that you want to use floating context menu in recycler view. Follow this method.

Now, since you did not specify why you want the menuinfo, so I'll take for an example that you want the item position to delete the view.

Because your code is similar to this.

All of the explanation is in reference to link in the first line.

When you long click on the view/item, onCreateContextMenu(...) is called and the view(which was long clicked) is sent along, copy that view in temporary variable inside the view holder.

The main part: How do you identify which list item/view was this? For this you can set a tag for each view in onBindHolder.

Use position as a tag (not necessary though).

Then call getTag() on the temporary view we saved in class ViewHolder.

Example Implementation:

 @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {

        holder.tvName.setText(holder.name);
        holder.tvName.setTag(position);

    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener,
                MenuItem.OnMenuItemClickListener {
            private final TextView tvName;
            private static final int DEL_ITEM_ID = 9116;
            private View toRemoveView;
            private String name;
            public ViewHolder(View view) {
                super(view);
                tvName = (TextView) view.findViewById(R.id.list_item);
                view.setOnCreateContextMenuListener(this);


   }

        @Override
        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
            menu.setHeaderTitle("Select action:");
            toRemoveView=v;
            MenuItem item = menu.add(0, DEL_ITEM_ID,100,"Delete");
            item.setOnMenuItemClickListener(this);
        }

        @Override
        public boolean onMenuItemClick(MenuItem item) {
            switch (item.getItemId()) {
                case DEL_ITEM_ID:
                    deleteRecord((Integer) toRemoveView.getTag());
                    //notifyItemRemoved(...) -- your wish
                    return true;
                default:
                    return false;
            }
        }

Caution I tested this when the number of items were just 2 and I deleted one (worked fine). I have not tested it when the list will scrolls. But since each item is assigned a unique tag (position), it shouldn't really cause any trouble.

I think I have made myself clear enough. If I am wrong somewhere, do correct me.

UPDATE: You can also call getAdapterPosition() inside viewholder class.I haven't tried it though.

Community
  • 1
  • 1
vishal-wadhwa
  • 1,021
  • 12
  • 18