Search code examples
androidandroid-recyclerviewnavigation-drawerfirebaseuiandroid-contextmenu

how to use context menu on recyclerview item provided by firebaseui


I would like to know how to put an contextmenu within a recyclerview item provided by FirebaseUI and be able to do some actions knowing which item was long pressed. Because when I try to use onCreateContextMenu on my holder class my ContextMenuInfo comes with null value.

Here is my holder class:

public class PlayerHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener {
    //private static final String TAG = PlayerHolder.class.getSimpleName();
    public TextView playerName;
    public TextView playerAge;
    
    public PlayerHolder(View itemView) {
        super(itemView);
        playerName = (TextView) itemView.findViewById(R.id.player_name);
        playerAge = (TextView) itemView.findViewById(R.id.player_age);
        itemView.setOnCreateContextMenuListener(this);
    }

    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        menu.add(0, 1, 0, "Edit");//groupId, itemId, order, title
        menu.add(0, 2, 0, "Share");
        menu.add(0, 3, 0, "Delete");
    }

    //@Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView .AdapterContextMenuInfo) item.getMenuInfo();
        switch (item.getItemId()) {
            case 1:
                //editNote(info.id);
                return true;
            case 2:
                //shareNote(info.id);
                return true;
            case 3:
                //deleteNote(info.id);
                return true;
            default:
                //return super.onContextItemSelected(item);
                return false;
        }
    }
}

and this is my firebaseui recycler adapter class:

public class PlayerAdapter extends FirebaseRecyclerAdapter<Player, PlayerHolder> {

    private static final String TAG = PlayerAdapter.class.getSimpleName();
    private Context context;

    public PlayerAdapter(Class<Player> modelClass, int modelLayout, Class<PlayerHolder> viewHolderClass, DatabaseReference ref, Context context) {
        super(modelClass, modelLayout, viewHolderClass, ref);
        this.context = context;
    }

    @Override
    protected void populateViewHolder(PlayerHolder viewHolder, Player model, int position) {
        
        viewHolder.playerName.setText(model.getName());
        viewHolder.playerAge.setText(String.valueOf(playerAge) + " Years");
    }
}

Solution

  • I've resolved this problem by use this solution in this post: How to create context menu for recycleview

    Here is my code:

    MessageViewHolder Class:

    public static class MessageViewHolder extends RecyclerView.ViewHolder  implements View.OnCreateContextMenuListener {
            public TextView tvMessage;
            public TextView tvDateSending;
            public CircleImageView ivMessenger;
            public LinearLayout linearLayout;
    
    
            public MessageViewHolder(View v) {
                super(v);
                tvMessage = (TextView) itemView.findViewById(R.id.tvMessage);
                tvDateSending = (TextView) itemView.findViewById(R.id.tvDateSending);
                ivMessenger = (CircleImageView) itemView.findViewById(R.id.ivMessenger);
                linearLayout= (LinearLayout) itemView.findViewById(R.id.llOneToOneChat);
                v.setOnCreateContextMenuListener(this);
    
            }
            public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
                menu.add(0,1 , 0, "Edit");
                menu.add(0, COPY, 0, "Copy");
                menu.add(0, DELETE, 0, "Delete");
            }
    
        }
    

    MessageAdapter class:

    public class MessageAdapter extends FirebaseRecyclerAdapter<Message, MessageViewHolder>{
    
            private Context context;
            private long prevMessageTime=0;
            public int position;
    
            public int getPosition() {
                return position;
            }
    
            public void setPosition(int position) {
                this.position = position;
            }
    
            public MessageAdapter(Class<Message> modelClass, int modelLayout, Class<MessageViewHolder> viewHolderClass, DatabaseReference ref, Context context) {
                super(modelClass, modelLayout, viewHolderClass, ref);
                this.context = context;
            }
    
            @Override
            protected void populateViewHolder(MessageViewHolder viewHolder, Message message, final int position) {
                //do something
                viewHolder.tvMessage.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View v) {
                        setPosition(position);
                        return false;
                    }
    
                });
            }
        }
    

    Finally in the Fragment/Activity override the onContextItemSelected as under:

    @Override
        public boolean onContextItemSelected(MenuItem item) {
            int position = -1;
            try {
                position = messageAdapter.getPosition();
            } catch (Exception e) {
    //            Log.d(TAG, e.getLocalizedMessage(), e);
                return super.onContextItemSelected(item);
            }
            switch (item.getItemId()) {
                case 1:
                    // do your stuff
    
                    break;
                case 2:
                    // copy message
                    if (position!= -1){
                        ClipboardManager clipboard = (ClipboardManager) OneToOneConversationActivity.this.getSystemService(Context.CLIPBOARD_SERVICE);
                        String text = messageAdapter.getItem(position).getMessage();
                        ClipData clip = android.content.ClipData.newPlainText("Copied Text", text);
                        clipboard.setPrimaryClip(clip);
    
                    }
    
                    break;
                case 3:
                    //delete message
                    if (position!= -1)
                        messageAdapter.getRef(position).removeValue();
                    break;
            }
            return super.onContextItemSelected(item);
        }
    

    Hope it works for you!