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 an recyclerview item provided by FirebaseUI and be able to do some actions knowing wich 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!