简体   繁体   中英

How do I get details of which item in a RecyclerView was clicked to generate a context menu?

I'm using a FirebaseRecyclerView to show a list of 'Charts' (defined in the app) in a Fragment in my app. The items in the list can be long-clicked to pop up a menu with options.

The difficulty I have is that when the user clicks on an item in the pop up menu, I can't get the id of the item that was clicked. I've included the relevant parts of ChartListFragment below, and marked where I'm having a problem.

public abstract class ChartListFragment extends Fragment {

    private FirebaseRecyclerAdapter<Chart, ChartViewHolder> mAdapter;
    private RecyclerView mRecycler;

    public ChartListFragment() {}

    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        View rootView = inflater.inflate(
                R.layout.fragment_charts_list, container, false);

        mRecycler = (RecyclerView) rootView.findViewById(R.id.charts_list);
        mRecycler.setHasFixedSize(true);

        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        LinearLayoutManager mManager = new LinearLayoutManager(getActivity());
        mManager.setReverseLayout(true);
        mManager.setStackFromEnd(true);
        mRecycler.setLayoutManager(mManager);

        DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
        Query chartsQuery = getQuery(mDatabase);
        mAdapter = new FirebaseRecyclerAdapter<Chart, ChartViewHolder>(Chart.class, R.layout.item_chart,
                ChartViewHolder.class, chartsQuery) {

            @Override
            protected void populateViewHolder(final ChartViewHolder viewHolder, final Chart model, final int position) {
                final DatabaseReference chartRef = getRef(position);
                final String chartKey = chartRef.getKey();

                registerForContextMenu(viewHolder.itemView);

                viewHolder.bindToPost(model);
            }
        };

        mRecycler.setAdapter(mAdapter);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);

        if (v.getId()==R.id.chart_item) {
            MenuInflater inflater = getActivity().getMenuInflater();
            inflater.inflate(R.menu.menu_long_press_chart_name, menu);
        }
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

    // AT THIS POINT I THINK I SHOULD BE ABLE TO GET THE POSITION OF THE ITEM
    // THAT WAS CLICKED BY DOING SOMETHING LIKE
    //      int chartPos = info.position;
    //      Chart chartClicked = mAdapter.getItem(chartPos);
    // BUT info IS NULL, SO info.position CAUSES A CRASH
        switch(item.getItemId()) {
            case R.id.edit:
                // Show Edit Activity
                return true;
            case R.id.delete:
                // Show confirmation message
                return true;
            default:
                return super.onContextItemSelected(item);
        }
    }

}

My solution has a lot of moving parts, but overall the concept is pretty simple: use an Intent to pass the data you want. You can't rely on the ContextMenu.ContextMenuInfo menuInfo parameter, because this is only present when your context menu is attached to a ListView or GridView .

The first step is you need to get all information you will eventually want (this could be position or it could be something more direct) into your ViewHolder . You need this because you can call RecyclerView.getChildViewHolder() in onCreateContextMenu in order to access the data associated with whichever item you clicked on.

The next step is to attach this data to the context menu using an Intent . In your onCreateContextMenu() implementation, after you inflate your menu, you can write something like this:

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    ...
    MyViewHolder holder = (MyViewHolder) recycler.getChildViewHolder(v);
    int position = holder.position; // or any custom data you want, set up in onBindViewHolder()

    Intent data = new Intent();
    data.putExtra("position", holder.position);
    menu.findItem(R.id.your_item_here).setIntent(data);
    menu.findItem(R.id.your_other_item_here).setIntent(data);
}

Finally, in your onContextItemSelected() implementation, you can access this Intent and get your data out of it:

@Override
public boolean onContextItemSelected(MenuItem item) {
    int position = item.getIntent().getIntExtra("position", -1);
    // do something with position
    return true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM