RecyclerView Databinding Item click

Robert J. picture Robert J. · Jan 15, 2018 · Viewed 7.7k times · Source

I am trying to listen for row clicks (item clicks) on my recycler view from the Activity itself (not from adapter).

My Adapter so far looks like this:

public class ListMiestnostiAdapter extends RecyclerView.Adapter<ListMiestnostiAdapter.ViewHolder>{
    private List<Miestnost> data;

    // you provide access to all the views for a data item in a view holder
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public ViewDataBinding binding;

        public ViewHolder(ViewDataBinding binding) {
            super(binding.getRoot());
            this.binding = binding;
        }

        public void bind(Object obj){
            binding.setVariable(BR.obj, obj);
            binding.executePendingBindings();
        }
    }

    public ListMiestnostiAdapter(List<Miestnost> data) {
        this.data = data;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // create a new view
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        ActivityListMiestnostiRowBinding itemBinding = ActivityListMiestnostiRowBinding.inflate(inflater, parent,false);

        return new ViewHolder(itemBinding);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Miestnost item = data.get(position);
        holder.bind(item);
    }

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

And my row layout like this:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="obj"
            type="com.example.com.projectname.Models.Miestnost" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?android:attr/selectableItemBackground"
        android:clickable="true"
        android:focusable="true"
        android:orientation="horizontal"
        android:paddingBottom="@dimen/row_padding_vertical"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/row_padding_vertical">

        <TextView
            android:id="@+id/txt_miestnost_row_nazov"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:text="@{obj.Name}"
            android:textSize="16dp" />
    </LinearLayout>
</layout>

As I have already mentioned I am trying to listen to item clicks, but not from Adapter itself (as other posts suggested), but from my Activity which holds this RecyclerView.

Is such action even possible? If yes, then any help would be highly appreciated as I could not find anything on google.

Answer

Jo&#227;o Alvares Neto picture João Alvares Neto · Jan 15, 2018

You’ll first need an interface that specifies listener’s behavior. In this example, there is a sample model called ContentItem, so the click will return an item of that type:

public interface OnItemClickListener {
    void onItemClick(ContentItem item);
}

The constructor will receive an object that implements this interface, along with the items to be rendered:

private final List<ContentItem> items;
private final OnItemClickListener listener;

public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) {
    this.items = items;
    this.listener = listener;
}

You could alternatively create a setOnItemClickListener method and assign it that way. Now, in onBindViewHolder the ViewHolder will receive the constructor in the custom bind method:

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    holder.bind(items.get(position), listener);
}

This is how this bind method looks:

public void bind(final ContentItem item, final OnItemClickListener listener) {
    ...
    itemView.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View v) {
            listener.onItemClick(item);
        }
    });
}

Use it whenever you need it by creating a new adapter and the listener that will implement the behavior when an item is clicked. A simple example:

recycler.setAdapter(new ContentAdapter(
    items,
    new ContentAdapter.OnItemClickListener() {
        @Override
        public void onItemClick(ContentItem item) {
            Toast.makeText(getContext(), "Item Clicked", Toast.LENGTH_LONG).show();
        }
    }));

Source