the_dani the_dani - 1 year ago 665
Android Question

Create Options Menu for RecyclerView-Item

How do I create an Options Menu like in the following Screenshot:

enter image description here

The Options Menu should be opened afther clicking on the "More"-Icon of a RecyclerView Item!

My try was this:

public void onBindViewHolder(Holder holder, int position) {
holder.txvSongInfo.setText(sSongs[position].getAlbum() + " - " + sSongs[position].getArtist());

holder.btnMore.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(mContext, "More...", Toast.LENGTH_SHORT).show();

But this causes problems because the full item is clicked if I touch on the RecyclerView Item More-Button...

Here's my RecyclerViewOnTouchListener:

public class RecyclerViewOnTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector mGestureDetector;
private OnTouchCallback mOnTouchCallback;

public RecyclerViewOnTouchListener(Context context, final RecyclerView recyclerView, final OnTouchCallback onTouchCallback) {
mOnTouchCallback = onTouchCallback;

mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
public boolean onSingleTapUp(MotionEvent e) {
return true;

public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());

if (child != null && onTouchCallback != null) {
onTouchCallback.onLongClick(child, recyclerView.getChildLayoutPosition(child));


public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());

if (child != null && mOnTouchCallback != null && mGestureDetector.onTouchEvent(e)) {
mOnTouchCallback.onClick(child, rv.getChildLayoutPosition(child));

return false;

public void onTouchEvent(RecyclerView rv, MotionEvent e) {


public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {


public interface OnTouchCallback {
void onClick(View view, int position);
void onLongClick(View view, int position);

I wasn't able to find any similar problem so I hope you can help me!

Answer Source

I found out that the only Menu, that looks like the Menu above is the PopupMenu.

So in onClick:

public void onClick(View view, int position, MotionEvent e) {
    ImageButton btnMore = (ImageButton) view.findViewById(;

    if (RecyclerViewOnTouchListener.isViewClicked(btnMore, e)) {
        PopupMenu popupMenu = new PopupMenu(view.getContext(), btnMore);

        getActivity().getMenuInflater().inflate(, popupMenu.getMenu());;

        //The following is only needed if you want to force a horizontal offset like margin_right to the PopupMenu
        try {
            Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup");
            Object oMenuHelper = fMenuHelper.get(popupMenu);

            Class[] argTypes = new Class[] {int.class};

            Field fListPopup = oMenuHelper.getClass().getDeclaredField("mPopup");
            Object oListPopup = fListPopup.get(oMenuHelper);
            Class clListPopup = oListPopup.getClass();

            int iWidth = (int) clListPopup.getDeclaredMethod("getWidth").invoke(oListPopup);

            clListPopup.getDeclaredMethod("setHorizontalOffset", argTypes).invoke(oListPopup, -iWidth);

        catch (NoSuchFieldException nsfe) {
        catch (NoSuchMethodException nsme) {
        catch (InvocationTargetException ite) {
        catch (IllegalAccessException iae) {
    else {

You have to make your onClick-Method pass the MotionEvent and finally implement the Method isViewClicked in your RecyclerViewOnTouchListener:

public static boolean isViewClicked(View view, MotionEvent e) {
    Rect rect = new Rect();


    return rect.contains((int) e.getRawX(), (int) e.getRawY());