Search code examples
androidandroid-recyclerviewonclicklistener

Setting OnClickListener on RecyclerView itself not on item


I want to set an OnClickListener on a RecyclerView, not on its items so that it triggers a click event when the user clicks on the RecyclerView (even if it is empty or full of items).

  • I'm using MVVM
  • I tried mRecyclerView.setClickable(true), not working

What I want

mRecyclerView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // do something
    }
});

My Adapter Class

public class TaskItemAdapter extends RecyclerView.Adapter<TaskItemAdapter.BaseItemAdapterViewHolder> {
    private static final String TAG = TaskItemAdapter.class.getSimpleName();
    private List<Task> mTaskList;
    private View.OnLongClickListener mOnLongClickListener;

    public TaskItemAdapter(List<Task> taskList, View.OnLongClickListener longClickListener) {
        mTaskList = taskList;
        mOnLongClickListener = longClickListener;
    }

    @NonNull
    @Override
    public BaseItemAdapterViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (parent instanceof RecyclerView) {
            int layoutId = R.layout.item_list_main;
            View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
            view.setFocusable(true);
            return new BaseItemAdapterViewHolder(view);

        } else {
            throw new RuntimeException(TAG + "Not bound to recyclerView");
        }
    }

    @Override
    public void onBindViewHolder(@NonNull BaseItemAdapterViewHolder holder, int position) {
        Task task = mTaskList.get(position);
        holder.mItemTextView.setText("- " + task.getName());

        holder.itemView.setTag(task);
        holder.itemView.setOnLongClickListener(mOnLongClickListener);
    }

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

    public void loadItems(List<Task> taskList) {
        mTaskList = taskList;
        notifyDataSetChanged();
    }

    public class BaseItemAdapterViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.item_textView)
        TextView mItemTextView;

        public BaseItemAdapterViewHolder(View view) {
            super(view);
            ButterKnife.bind(this, view);
        }
    }
}

Solution

  • I manage to do it by:

    I pass two listeners to the adapter:

    View.OnClickListener;
    View.OnTouchListener;
    

    In method onCreateViewHolder I set the two listeners and pass the recyclerViewID into a tag.

    int layoutId = R.layout.item_list_main;
    View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
    view.setFocusable(true);
    parent.setOnTouchListener(mOnTouchListener);
    view.setTag(R.id.PARENT_VIEW_ID, parent.getId());
    view.setOnClickListener(mOnClickListener);
    return new BaseItemAdapterViewHolder(view);
    

    In main activity:

    1. View.OnTouchListener operate in empty space of recyclerView itself.
    2. View.OnClickListener operate in the items of recyclerView.
    3. And used an empty layout click listener.

    So now whatever the user clicks on recyclerView or its item, or its empty state it will trigger as a whole click.