Tuesday, May 12, 2015

Adding context menus to RecyclerView items


Add an affordance

The "three-dot" overflow pattern was my first choice.





Setup click listeners in ViewHolder


        private ImageView mOverflowIcon;

        public FileViewHolder(View holdMe) {
            super(holdMe);
            holdMe.setOnClickListener(this);
            holdMe.setOnLongClickListener(this);
            mOverflowIcon = (ImageView) holdMe.findViewById(R.id.mfp_context_menu);
            mOverflowIcon.setOnClickListener(this);
        }

Create context menu in OnClickListener

Display the PopupMenu. ("this" is the ViewHolder)

        @Override
        public void onClick(View v) {
            if (v == mOverflowIcon) {
                PopupMenu popup = new PopupMenu(v.getContext(), v);
                popup.inflate(R.menu.mfp_overflow_menu_file);
                popup.setOnMenuItemClickListener(this);
                popup.show();
            }
        }

The menu xml.

        <?xml version="1.0" encoding="utf-8"?>
        <menu xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto">
            <item
                android:id="@+id/delete_file"
                android:title="@string/mfp_delete"
                app:showAsAction="always" />
        </menu>

Add your logic for the menu items

Just the implementation of the OnMenuItemClickListener, and since it's the ViewHolder you have the data as well.

        @Override
        public boolean onMenuItemClick(MenuItem item) {
            Toast.makeText(mOverflowIcon.getContext(),"DO SOME STUFF HERE", Toast.LENGTH_LONG).show();
            return true;
        }

NOTE: WindowLeaked

Just a note, if an orientation change occurs while the PopupMenu is still showing you will get a nice informative WindowLeaked exception. This does not crash your app, it is just poor practice. You need to call popupMenu.dismiss() when the activity context is being destroyed, your resulting code for that may vary depending on your implementation.