Reputation: 387
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
Reputation: 57
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
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
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
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