Carl
Carl

Reputation: 861

Android RecyclerView Clicks

I am trying to achieve the functionality seen on Google Play where a CardView has an options menu that can be clicked and you can click on the card to view more detail on the card.

I have implemented an OnItemTouch listener on my RecyclerView which works fine and responds when touched, taking me to another activity. However, when I now try and add a click listener to an options icon I have added within the RecyclerView item (which is a CardView), the OnItemTouch listener is called. Can anyone help?

Activity

mRecyclerView.addOnItemTouchListener(
            new RecyclerItemClickListener(this, new RecyclerItemClickListener.OnItemClickListener() {
                @Override
                public void onItemClick(View view, int position) {
                    Intent intent = new Intent(getApplicationContext(),
                            TransactionDetailActivity.class);
                    Bundle bundle = new Bundle();
                    bundle.putSerializable("transaction_key", mTransactionList.get(position));
                    intent.putExtras(bundle);
                    startActivity(intent);
                }
            })
    );        mRecyclerView.setAdapter(mAdapter);

Click Listener

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
    private OnItemClickListener mListener;

    public interface OnItemClickListener {
        public void onItemClick(View view, int position);
    }

    GestureDetector mGestureDetector;

    public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
    mListener = listener;
    mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return true;
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e)    {
        View childView = view.findChildViewUnder(e.getX(), e.getY());
        if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
            mListener.onItemClick(childView, view.getChildPosition(childView));
            return true;
        }
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    }
}

Upvotes: 0

Views: 100

Answers (2)

backslashN
backslashN

Reputation: 2875

If you don't want to handle the clicks of CardView children, OnItemTouchListener is the way.

But if you want to handle the cliks of cardview children, you may have to attach OnClickListener (in the Adapter class' DataObjectHolder or onBindViewHolder method) to the CardView or its immediate child (which can be any layout Eg. LinearLayout, RelativeLayout, etc) to handle the card clicks. If done so, the OnClickListener of any view inside the CardView will work.

Following is an example:

Adapter

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.DataObjectHolder>{

    Context context;
    ArrayList<String> list;
    static String TAG = "ApprovalsRV Adapter";
    DeleteListener deleteListener;

    public RecyclerViewAdapter(Context context, ArrayList<String> list)
    {
        this.context = context;
        this.list = list;
        deleteListener = (DeleteListener) context;
    }

    public static class DataObjectHolder extends RecyclerView.ViewHolder
    {
        TextView tName;
        RelativeLayout rlName;
        CardView cvName;

        public DataObjectHolder(View itemView, final Context context)
        {
            super(itemView);
            tName = (TextView) itemView.findViewById(R.id.tName);
            rlName = (RelativeLayout) itemView.findViewById(R.id.rlName);
            cvName = (CardView) itemView.findViewById(R.id.cvName);

            cvName.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View view) {
                    //Handle the card click here
                    deleteListener.deleteName(position); // if handling from activity (explained below)
                }
            });

            tName.setOnClickListener(new View.OnClickListener() 
            { //You can have similar listeners for subsequent children
                @Override
                public void onClick(View view) {
                    //Handle the textview click here
                }
            });
        }
    }

    @Override
    public DataObjectHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.card_view_layout, parent, false);
        DataObjectHolder dataObjectHolder = new DataObjectHolder(view, context);
        return dataObjectHolder;
    }

    @Override
    public void onBindViewHolder(DataObjectHolder holder, int position)
    {
        holder.tName.setText(list.get(position));
    }

    @Override
    public int getItemCount() {
        return list.size();
    }
}

If you want to handle the card click from the activity, you will need to use an interface here.

DeleteListener.java

public interface DeleteListener {
    public void deleteName(int position);
}

Now to use this in your activity:

MyActivity.java

public class MyActivity extends AppCompatActivity implements DeleteListener
{
    @Override
    public void deleteName(int position) {
        //Your job
    }
}

This will clear your doubt.

Upvotes: 1

Bob
Bob

Reputation: 13865

Instead of using OnItemTouchListener to handle RecyclerView item click events, use OnClickListener for the itemView which you get in the ViewHolder.

public class MyViewHolder extends RecyclerView.ViewHolder implements OnClickListener{
    public MyViewHolder(View itemView){
        super(itemView);
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v){
        // handle click event
    }

}

So, when the options icon is pressed, the whole itemView ClickListener will not be called.

Upvotes: 0

Related Questions