Data binding in adapter of recyclerView - Android
Asked Answered
T

5

6

I am using dataBinding in my project to populate a RecyclerView. How can I handle clicks on items?

Here is my XML layout:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="listItems"
            type="String" />

        <variable
            name="clickListener"
            type="com.xxxx.xxxx.AdapterStartActivity" />
    </data>

    <android.support.v7.widget.CardView
        android:id="@+id/cardview1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="3dp"
        android:onClick="@{()->clickListener.onCardClick(listItems)}" <=====
        card_view:cardCornerRadius="7dp"
        card_view:cardElevation="7dp"
        card_view:cardMaxElevation="7dp"
        card_view:contentPadding="0dp">

        <TextView
            android:id="@+id/txtTitles"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:gravity="center"
            android:padding="10dp"
            android:text="@{listItems}"
            android:textColor="#000000"
            android:textSize="20dp"
            android:textStyle="bold" />
    </android.support.v7.widget.CardView>
</layout>

I specified the onClick handler in this line:

android:onClick="@{()->clickListener.onCardClick(listItems)}"

And below is my adapter:

public class AdapterStartActivity extends RecyclerView.Adapter<AdapterStartActivity.ViewHolder> {
    private ListItemActivityStartBinding binding;
    private List<String> listTitle;
    private Context context;

    public AdapterStartActivity(Context context, List<String> listTitle) {
        this.listTitle = listTitle;
        this.context = context;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView txtTitles;

        public ViewHolder(View v) {
            super(v);
            txtTitles = (TextView) v.findViewById(R.id.txtTitles);
        }
    }

    @Override
    public AdapterStartActivity.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.list_item_activity_start, parent, false);
        binding = DataBindingUtil.bind(view);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ViewHolder Vholder, int position) {
        binding.setListItems(listTitle.get(position));
    }

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

    public void onCardClick(String listItems) {
        Log.i("SADASSDASDAS", listItems);
    }
}

However, the following code doesn't work:

public void onCardClick(String listItems) {
    Log.i("SADASSDASDAS", listItems);
}
Thiourea answered 11/7, 2017 at 5:36 Comment(0)
T
1

Your main problem is that you are missing a call to binding.setClickListener(). There are a few other issues. Here is an example that should get you on the right track, ignore the parts that you don't need: What is the recommended way to launch a DialogFragment from a ViewModel?

Tamarisk answered 11/7, 2017 at 6:13 Comment(3)
@Uli.How can I get the position of items when clicked ??Thiourea
Resolved my problem with : binding.getRoot().setTag(position); and view.getTag(). ;)Thiourea
@JoJoRoid RecyclerView.ViewHolder has several methods for obtaining position information, most commonly you'd want ViewHolder.getAdapterPosition().Tamarisk
M
10

Data binding in adapter of RecyclerView - Android

public class DashboardPopularAdapter extends RecyclerView.Adapter<DashboardPopularAdapter.MyViewHolder> {
    private Context mContext;
    private List<PopularProduct> mPopularProductInfos;

    public DashboardPopularAdapter(Context context, List<PopularProduct> popularProductInfos) {
        mContext = context;
        mPopularProductInfos = popularProductInfos;
    }

    @Override
    public DashboardPopularAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int type) {
        ViewDashboardProductsBinding viewProductCategoryBinding = ViewDashboardProductsBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
        return new MyViewHolder(viewProductCategoryBinding);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        final PopularProduct popularProductInfo = mPopularProductInfos.get(position);

        holder.binding.txtProductName.setText(popularProductInfo.getProductName());

        Picasso.with(mContext).load(popularProductInfo.getProductPhoto())
                .error(R.drawable.icon_pills)
                .into(holder.binding.imgProduct);

        holder.binding.llProduct.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mContext.startActivity(new Intent(mContext, ProductDetailsActivity.class)
                        .putExtra("medicine_id", popularProductInfo.getProductId())
                        .putExtra("medicine_name", popularProductInfo.getProductName()));
            }
        });

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

    public static class MyViewHolder extends RecyclerView.ViewHolder {
        private final ViewDashboardProductsBinding binding;

        public MyViewHolder(ViewDashboardProductsBinding binding) {
            super(binding.getRoot());
            this.binding = binding;
        }
    }
}
Mongol answered 7/3, 2018 at 12:56 Comment(0)
B
2
public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.ViewHolder> {
    StudentListRowBinding listRowBinding;
    ArrayList<Student> studentlist;

    public StudentAdapter(ArrayList<Student> studentlist) {
        this.studentlist = studentlist;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
       
        listRowBinding= DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),R.layout.student_list_row,parent,false);
        return new ViewHolder(listRowBinding.getRoot());
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
            /*listRowBinding.stuname.setText(studentlist.get(position).getName());
            listRowBinding.stumob.setText(studentlist.get(position).getMobile());
            listRowBinding.stucity.setText(studentlist.get(position).getCity());  */

        holder.stuname.setText(studentlist.get(position).getName());
        holder.stumob.setText(studentlist.get(position).getMobile());
        holder.stucity.setText(studentlist.get(position).getCity());


        if (position == getItemCount() - 1)
            holder.divider.setVisibility(View.GONE);
    }

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

    class ViewHolder extends RecyclerView.ViewHolder {
        TextView stuname, stumob, stucity;
        View divider;

        public ViewHolder(View itemView) {
            super(itemView);
            stuname = (TextView) itemView.findViewById(R.id.stuname);
            stumob = (TextView) itemView.findViewById(R.id.stumob);
            stucity = (TextView) itemView.findViewById(R.id.stucity);
            divider = itemView.findViewById(R.id.divider);
        }
    }


}
Bathysphere answered 11/7, 2017 at 7:46 Comment(0)
T
1

Your main problem is that you are missing a call to binding.setClickListener(). There are a few other issues. Here is an example that should get you on the right track, ignore the parts that you don't need: What is the recommended way to launch a DialogFragment from a ViewModel?

Tamarisk answered 11/7, 2017 at 6:13 Comment(3)
@Uli.How can I get the position of items when clicked ??Thiourea
Resolved my problem with : binding.getRoot().setTag(position); and view.getTag(). ;)Thiourea
@JoJoRoid RecyclerView.ViewHolder has several methods for obtaining position information, most commonly you'd want ViewHolder.getAdapterPosition().Tamarisk
P
0

Android just implements the OnClickListener for you when you define the android:onClick="someMethod" attribute, so try this code.

Code Implementation

public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView txtTitles;

        public ViewHolder(View v) {
            super(v);
            txtTitles = (TextView) v.findViewById(R.id.txtTitles);
        }

        v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    onCardClick(listItems)
                }
        });
    }
Pair answered 11/7, 2017 at 5:56 Comment(0)
H
0

Here is the adapter class for data binding:

class MyBasketAdapter(
        items: List<GetBasketData>,
        private val itemClick: (view: View, position: Int, getBasketData: GetBasketData?) -> Unit)
    : RecyclerView.Adapter<MyBasketAdapter.ViewHolder>() {

// refresh items
var items = items
    set(value) {
        field = value
        notifyDataSetChanged()
    }

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    return ViewHolder(
        DataBindingUtil.inflate(
            LayoutInflater.from(parent.context),
            R.layout.item_my_basket,
            parent,
            false
        )
    )
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.bind(position)
    holder.itemView.setOnClickListener(holder)
    holder.itemView.ibDelete.setOnClickListener(holder)
}

override fun getItemCount(): Int {
    return items.count()
}

inner class ViewHolder(private val binding: ItemMyBasketBinding) :
    RecyclerView.ViewHolder(binding.root), View.OnClickListener {

    override fun onClick(v: View?) {
        v?.let {
            itemClick.invoke(it, adapterPosition, items[adapterPosition])
        }
    }

    fun bind(
        position: Int
    ) {
        binding.basketData = items[position]
        binding.executePendingBindings()
    }
}

and this is my item_my_basket.xml file

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

    <import type="android.view.View" />

    <import type="com.gobaskt.ui.utils.DateTimeUtil" />

    <import type="com.gobaskt.ui.utils.extensions.BindingAdapters" />

    <variable
        name="basketData"
        type="com.gobaskt.ui.bottomnavigation.basket.model.GetBasketData" />

</data>

<com.google.android.material.card.MaterialCardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:cardBackgroundColor="@color/white"
    app:cardCornerRadius="0dp"
    app:cardElevation="0dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_item_dotted_line_blue_2dp">

        <com.google.android.material.radiobutton.MaterialRadioButton
            android:id="@+id/rbSelectItem"
            android:layout_width="@dimen/_10sdp"
            android:layout_height="@dimen/_10sdp"
            android:background="@drawable/my_basket_rb_selector"
            android:button="@color/transparent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/imgProduct"
            android:layout_width="@dimen/_62sdp"
            android:layout_height="@dimen/_62sdp"
            android:layout_marginStart="@dimen/_4sdp"
            android:layout_marginTop="@dimen/_8sdp"
            android:layout_marginBottom="@dimen/_8sdp"
            android:adjustViewBounds="true"
            app:actualImageScaleType="centerInside"
            app:imageUriForFresco="@{basketData.offers.mobileOfferImage1}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@id/rbSelectItem"
            app:layout_constraintTop_toTopOf="parent"
            app:placeholderImage="@drawable/ic_place_holder"
            app:placeholderImageScaleType="centerCrop"
            app:roundAsCircle="true" />

        <com.google.android.material.textview.MaterialTextView
            android:id="@+id/txtProductName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/_8sdp"
            android:layout_marginEnd="@dimen/_4sdp"
            android:ellipsize="end"
            android:fontFamily="@font/montserrat_medium"
            android:maxLines="1"
            android:text="@{basketData.offers.lmName}"
            android:textColor="@color/black"
            android:textSize="@dimen/_13ssp"
            app:layout_constraintBottom_toTopOf="@+id/txtValidOn"
            app:layout_constraintEnd_toStartOf="@+id/txtOffValue"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/imgProduct"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_chainStyle="packed"
            tools:text="Jursey Mike’s Subs" />

        <com.google.android.material.textview.MaterialTextView
            android:id="@+id/txtValidOn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/_8sdp"
            android:layout_marginTop="@dimen/_2sdp"
            android:layout_marginEnd="@dimen/_4sdp"
            android:ellipsize="end"
            android:fontFamily="@font/montserrat_light"
            android:maxLines="1"
            android:text="@{basketData.offers.offerTermsAndConditions}"
            android:textColor="@color/black"
            android:textSize="@dimen/_9ssp"
            app:layout_constraintBottom_toTopOf="@+id/txtValidTill"
            app:layout_constraintEnd_toStartOf="@+id/txtOffValue"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/imgProduct"
            app:layout_constraintTop_toBottomOf="@+id/txtProductName"
            tools:text="Only on Hot subs" />

        <com.google.android.material.textview.MaterialTextView
            android:id="@+id/txtValidTill"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/_8sdp"
            android:layout_marginTop="@dimen/_2sdp"
            android:ellipsize="end"
            android:fontFamily="@font/montserrat_medium"
            android:maxLines="1"
            android:text="@string/valid_till"
            android:textColor="@color/black"
            android:textSize="@dimen/_9ssp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@+id/imgProduct"
            app:layout_constraintTop_toBottomOf="@+id/txtValidOn" />

        <com.google.android.material.textview.MaterialTextView
            android:id="@+id/txtValidTillDate"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/_4sdp"
            android:layout_marginEnd="@dimen/_8sdp"
            android:ellipsize="end"
            android:fontFamily="@font/montserrat_medium"
            android:maxLines="1"
            android:text="@{basketData.offers.offerExpiryDate}"
            android:textColor="@color/orange_f87733"
            android:textSize="@dimen/_9ssp"
            app:layout_constraintBottom_toBottomOf="@id/txtValidTill"
            app:layout_constraintEnd_toStartOf="@id/ibDelete"
            app:layout_constraintStart_toEndOf="@+id/txtValidTill"
            app:layout_constraintTop_toTopOf="@id/txtValidTill"
            tools:text="9th Oct" />

        <com.google.android.material.textview.MaterialTextView
            android:id="@+id/txtOffValue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="@dimen/_4sdp"
            android:fontFamily="@font/montserrat_bold"
            android:text="@{basketData.offers.lmOfferValue +``+basketData.offers.lmOfferType}"
            android:textColor="@color/blue_2d3263"
            android:textSize="@dimen/_15ssp"
            app:layout_constraintBottom_toBottomOf="@+id/txtProductName"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/txtProductName"
            app:layout_constraintTop_toTopOf="@+id/txtProductName"
            tools:text="15 %" />

        <androidx.appcompat.widget.AppCompatImageButton
            android:id="@+id/ibDelete"
            android:layout_width="@dimen/_30sdp"
            android:layout_height="@dimen/_30sdp"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:backgroundTint="@color/transparent"
            android:clickable="true"
            android:focusable="true"
            android:src="@drawable/ic_delete_basket_item"
            app:layout_constraintBottom_toBottomOf="@+id/txtValidTillDate"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/txtValidTillDate"
            app:layout_constraintTop_toTopOf="@+id/txtValidTillDate" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</com.google.android.material.card.MaterialCardView>
Hola answered 16/3, 2020 at 5:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.