sixcookies
sixcookies

Reputation: 387

Android: How to check if a Checkbox is checked in an item of a RecyclerView

I've been trying to find out how I could check if a checkbox was checked in a list item in a RecyclerView. I have seen some articles online but I could not understand what they meant. If anyone could help, that'd be great.

Info about my app This is a little snippet of what it does. It is a contacts app. On one screen it lists out ALL of the user's contacts. I didn't use the contacts picker for this. I displayed the list as a recyclerview, each item in the recyclerview has a checkbox. The user can check the checkbox for the contacts that they want to star. When they hit the save button the contacts that they checked will be on their favourites page which is the MainActivity.

I now need to find out how to see if an item is checked in a recycler view.

Here is the code for the adapter:

package krispo.callaid;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CheckedTextView;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

/**
 * Created by po on 9/8/2018.
 */

public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.MyViewHolder> {

private List<Contact> contactsList;


public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView name, number;
    public CheckBox checkBox;
    public MyViewHolder(View view) {
        super(view);
        name = (TextView) view.findViewById(R.id.name);
        number = (TextView) view.findViewById(R.id.number);
        checkBox = (CheckBox)view.findViewById(R.id.checkBox);


    }
}


public ContactAdapter(List<Contact> contactsList) {
    this.contactsList = contactsList;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.contact_row, parent, false);

    return new MyViewHolder(itemView);
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    Contact contact = contactsList.get(position);
    holder.name.setText(contact.getName());
    holder.number.setText(contact.getPhoneNumber());

}

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

}

And this is the code for the contacts object:

package krispo.callaid;

import android.preference.CheckBoxPreference;

public class Contact {

private String name, phoneNumber,ID;
private boolean added;
private int position;


public Contact(){

}

    public Contact(String name, String phoneNumber,String ID, boolean added){
    this.name = name;
    this.phoneNumber = phoneNumber;
    this.ID = ID;
    this.added = added;
}

public String getName() {
    return this.name;
}

public void setName(String name) {
    this.name = name;
}

public String getPhoneNumber() {
    return this.phoneNumber;
}

public void setPhoneNumber(String phoneNumber) {
    this.phoneNumber = phoneNumber;
}

public String getID() {
    return this.ID;
}

public void setID(String ID) {
    this.ID = ID;
}

public boolean isAdded() {
    return this.added;
}

public void setAdded(boolean added) {
    this.added = added;
}

public int getPosition() {
    return position;
}

public void setPosition(int position) {
    this.position = position;
}
}

Here is the code for each item's row:

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?android:attr/selectableItemBackground"
    android:clickable="true"
    android:focusable="true"
    android:orientation="vertical"
    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/name"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_toEndOf="@+id/checkBox"
    android:layout_toRightOf="@+id/checkBox"
    android:text="Test"
    android:textColor="@android:color/black"
    android:textSize="25sp"
    android:textStyle="bold" />

<TextView
    android:id="@+id/number"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/name"
    android:layout_toEndOf="@+id/checkBox"
    android:layout_toRightOf="@+id/checkBox"
    android:text="Test"
    android:textColor="#7f8c8d"
    android:textSize="20sp" />

<CheckBox
    android:id="@+id/checkBox"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_toRightOf="@+id/number"
    android:layout_centerVertical="true" />

</RelativeLayout>

Thank you! I'm a bit new at this so sorry if it's a bit messy.

Upvotes: 2

Views: 4232

Answers (4)

I use this for solution:

  • Step 1: Create a ViewModel with LiveData for Id select

    val selectIds = MutableLiveData<ArrayList<Boolean>>()
    
  • Step 2: add all data with position to value of selectIds, I use listAdapter, so I can get all data from currentList of adapter. In my code:

    adapter.submitList(adapter.currentList.sortedBy { it1 -> it1.dateCreate 
    })
                  adapter.currentList.sortedBy { it1 -> it1.dateCreate }.also 
    { it2 ->
                      scannerViewModel.selectIds.value = ArrayList()
                      scannerViewModel.selectIds.value?.clear()
                      for (item in it2) {
    
    scannerViewModel.selectIds.value?.add(it2.indexOf(item), false)
                      }
                  }
    
  • Step 3: on func onBindViewHolder of Adapter, check status checked of view by:

     holder.itemScanBinding.isChecked =
              scannerViewModel.selectIds.value!![position]
    
  • Step 4: And you add this on event onClick of check view:

    scannerViewModel.selectIds.value?.set(
                  position,
                  holder.itemScanBinding.btnSelect.isChecked
              )
    
  • Done. Hope this help you.

Upvotes: 0

Jeet Karmakar
Jeet Karmakar

Reputation: 94

The main problem is once you check an item and scroll the recycler view up or down such that the item goes out of the view, recycler view does not properly maintain the items which were checked while recreating the view. To maintain the state of the checked items, I have modified your adapter class as below:

package krispo.callaid;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CheckedTextView;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;

import com.cashrich.cashrich.adapter.WithdrawCardAdapter;

import java.text.DecimalFormat;
import java.util.List;

/**
 * Created by po on 9/8/2018.
 */

public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.MyViewHolder> {

    private List<Contact> contactsList;
    private Boolean[] chkArr;


    public class MyViewHolder extends RecyclerView.ViewHolder implements CheckboxListener {
        public TextView name, number;
        public CheckBox checkBox;
        public CustomSwitchListener myCustomSwitchListener;
        public MyViewHolder(View view,CustomSwitchListener myCustomSwitchListener) {
            super(view);
            name = (TextView) view.findViewById(R.id.name);
            number = (TextView) view.findViewById(R.id.number);
            checkBox = (CheckBox)view.findViewById(R.id.checkBox);
            this.myCustomSwitchListener=myCustomSwitchListener;
            checkBox.setOnCheckedChangeListener(myCustomSwitchListener);
        }

        @Override
        public  void updateCheck(int pos,boolean val)
        {
            if(val)
            {
                checkBox.setChecked(true);
            }
            else
            {
                checkBox.setChecked(false);
            }
        }
    }

    public Boolean[] getSelectedIds() {
        return chkArr;
    }

    public ContactAdapter(List<Contact> contactsList) {
        this.contactsList = contactsList;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.contact_row, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        Contact contact = contactsList.get(position);
        holder.name.setText(contact.getName());
        holder.number.setText(contact.getPhoneNumber());

    }

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


    public interface CheckboxListener{
        void updateCheck(int pos,boolean val);
    }

    private class CustomSwitchListener implements CompoundButton.OnCheckedChangeListener {
        private int position;
        CheckboxListener checkboxListener;


        /**
         * Updates the position according to onBindViewHolder
         *
         * @param position - position of the focused item
         */
        public void updatePosition(int position,MyViewHolder holder) {
            this.position = position;
            checkboxListener=(CheckboxListener) holder;
        }

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            chkArr[position]=isChecked;
            if(isChecked)
            {
                checkboxListener.updateCheck(position,true);
            }
            else
            {
                checkboxListener.updateCheck(position,false);
            }
        }
    }
}

This implements a class to maintain the state of the checked items and inform the same to the adapter while recreating the views. You can get the list of selected items with this variable private Boolean[] chkArr;

Upvotes: 0

Mehul Kanzariya
Mehul Kanzariya

Reputation: 1348

Create an ArrayList named checkedContacts of type Contact and in the onBindViewHolder method, set a check listener for the CheckBox and add or remove the Contact from the checkedContacts as shown below:

holder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        if (isChecked){
            checkedContacts.add(contact);
        } else {
            checkedContacts.remove(contact);
     }
    }

});

Upvotes: 2

Aanal Shah
Aanal Shah

Reputation: 283

change your adapter
- take a list of ids
- add contact id while it checked

public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.MyViewHolder> {

private List<Contact> contactsList;
private List<Integer> mSelectedItemsIds;

public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView name, number;
    public CheckBox checkBox;
    public MyViewHolder(View view) {
        super(view);
        name = (TextView) view.findViewById(R.id.name);
        number = (TextView) view.findViewById(R.id.number);
        checkBox = (CheckBox)view.findViewById(R.id.checkBox);


    }
}


public ContactAdapter(List<Contact> contactsList) {
    this.contactsList = contactsList;
    mSelectedItemsIds = new ArrayList<>();
}

public List<Integer> getSelectedIds() {
    return mSelectedItemsIds;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.contact_row, parent, false);

    return new MyViewHolder(itemView);
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    Contact contact = contactsList.get(position);
    holder.name.setText(contact.getName());
    holder.number.setText(contact.getPhoneNumber());
    holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if(isChecked){
                mSelectedItemsIds.add(position);
            }else{
                mSelectedItemsIds.remove(position);
            }
        }
    });

}

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

to get selectedids

  List<Integer> selectedid =  ContactAdapter.getSelectedIds();

put this do whatever with selected ids

Upvotes: 0

Related Questions