How to Select Only One Checkbox in Recyclerview and Notifydataset Changed

How can I select only one checkbox in Recyclerview and notifydataset changed

this is the best code!
notice onBindViewHolder

public class SupportSchoolIdAdapter extends RecyclerView.Adapter<SupportSchoolIdAdapter.ViewHolder > {

private Context context;
ArrayList<SupportSchoolIdModel> supportSchoolIdModels;
private int selectedPosition = 0;
private ArrayList<Integer> selectCheck = new ArrayList<>();

public SupportSchoolIdAdapter (Context context, ArrayList<SupportSchoolIdModel> supportSchoolIdModels) {
this.context = context;
this.supportSchoolIdModels = supportSchoolIdModels;

//initilize selectCheck
for (int i = 0; i < supportSchoolIdModels.size(); i++) {
selectCheck.add(0);
}

}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.support_school_item, parent, false);
return new ViewHolder(v);
}

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

if (selectCheck.get(position) == 1) {
holder.checkbox.setChecked(true);
} else {
holder.checkbox.setChecked(false);
}

holder.checkbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for(int k=0; k<selectCheck.size(); k++) {
if(k==position) {
selectCheck.set(k,1);
} else {
selectCheck.set(k,0);
}
}
notifyDataSetChanged();

}
});
holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

if(isChecked==true){
//Do whatever you want to do with selected value
}
}
});

}

@Override
public int getItemCount() {
return supportSchoolIdModels== null? 0: supportSchoolIdModels.size();
}

class ViewHolder extends RecyclerView.ViewHolde {

CheckBox checkbox;

public ViewHolder(View v) {
super(v);
checkbox = (CheckBox) v.findViewById(R.id.checkbox);
}

}

}

Select one checkBox in item from recyclerView and deselect previously selected checkBox

Inside your Adapter

use this :

private int row_index;

   @Override
public void onBindViewHolder(final Main_Page_Payment_Cash_Adapter.ViewHolder holder, final int position) {

holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// checkbox.setChecked(true);
row_index = position;
notifyDataSetChanged();
}
});

if (row_index == position) {
// checkbox.setChecked(true);
} else {
// checkbox.setChecked(false);
}
}

I hope this is what you are looking for.

RecyclerView and notifyDataSetChanged LongClick mismatch

The problem is you're holding your checked state in the ViewHolder itself - you're toggling its checkbox on and off depending on clicks, right?

The way a RecyclerView works is that instead of having a ViewHolder for every single item (like a ListView does), it only creates a handful of them - enough for what's on screen and a few more for scrolling - and recycles those, using them to display different items.

That's what onBindViewHolder is about - when it needs to display the item at position, it hands you a ViewHolder from its pool and says here you go, use that to display this item's details. This is where you do things like setting text, changing images, and setting things like checkbox state to reflect that particular item.


What you're doing is you're not storing the item's state anywhere, you're just setting the checkbox on the view holder. So if you check it, every item that happens to be displayed in that reusable holder object will have its box ticked. That's why you're seeing it pop up on other items - that checked state has nothing to do with the items themselves, just which view holder they all happen to use because of their position in the list.

So instead, you need to keep their checked state somewhere - it could be as simple as a boolean array that matches the length of your item list. Then you just set and get from that when binding your data (displaying it). Working with what you've got:

// all default to false
val itemChecked = BooleanArray(items.size)

override fun onBindViewHolder(holder: Holder, position: Int) {
...
// when displaying the data, refer to the checked state we're holding
holder.binding.checkbox.checked = itemChecked[position]
...
holder.itemView.setOnLongClickListener {
...
// when checking the box, update our checked state
// since we're calling notifyDataSetChanged, the item will be redisplayed
// and onBindViewHolder will be called again (which sets the checkbox)
itemChecked[position] = true
// notifyItemChanged(position) is better here btw, just refreshes this one
notifyDataSetChanged()
...
}
}

how to have single choice on checkbox in recyclerview?

you should define a state for each value of your list that you passed to your adapter.whit this state you can decide which checkbox must be checked or not. when a change occurs in items of adapter you must be notified with a listener in your activity and made a change to the state of each item of the list.
after that, just a simple adapter.notifyDataSetChanged() can make everything ok!

I try to make it clear with the sample code below :

Activity is something like this :

class MainActivity : AppCompatActivity(), Adapter.OnItemClick {

private val items = ArrayList<ListItems>()

private lateinit var adapter: Adapter

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.toolbar))

items.add(ListItems(0, isChecked : false, checkable : true))
items.add(ListItems(1, isChecked : false, checkable : true))
items.add(ListItems(2, isChecked : false, checkable : true))

adapter = Adapter(items, this)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)



}


override fun onItemClicked(position: Int, state: Boolean) {
Log.i("MainActivity", "onItemClicked: position :")
items.get(position).state = state
if (!state) {
for (item in items) {
item.checkable = true
}
} else {
for (x in 0 until items.size) {
items.get(x).checkable = x == position

}
}

adapter.notifyDataSetChanged()


}

and the adapter class :

class Adapter(val items: ArrayList, val onItemClick: OnItemClick) :
RecyclerView.Adapter<Adapter.ViewHolder>() {

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

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

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val checkBox = holder.itemView.findViewById<CheckBox>(R.id.checkbox)
checkBox.isChecked = items.get(position).state
checkBox.isEnabled = items.get(position).editable
checkBox.setOnCheckedChangeListener(object :
CompoundButton.OnCheckedChangeListener {
override fun onCheckedChanged(p0: CompoundButton?, check:
Boolean) {
if (check) {
onItemClick.onItemClicked(position, true)
} else
onItemClick.onItemClicked(position, false)
}
})
}

class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
}

interface OnItemClick {
fun onItemClicked(position: Int, state: Boolean)
}

}

Single selection in RecyclerView

The solution for the issue:

public class yourRecyclerViewAdapter extends RecyclerView.Adapter<yourRecyclerViewAdapter.yourViewHolder> {

private static CheckBox lastChecked = null;
private static int lastCheckedPos = 0;


public void onBindViewHolder(ViewHolder holder, final int position) {

holder.mTextView.setText(fonts.get(position).getName());
holder.checkBox.setChecked(fonts.get(position).isSelected());
holder.checkBox.setTag(new Integer(position));

//for default check in first item
if(position == 0 && fonts.get(0).isSelected() && holder.checkBox.isChecked())
{
lastChecked = holder.checkBox;
lastCheckedPos = 0;
}

holder.checkBox.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
CheckBox cb = (CheckBox)v;
int clickedPos = ((Integer)cb.getTag()).intValue();

if(cb.isChecked())
{
if(lastChecked != null)
{
lastChecked.setChecked(false);
fonts.get(lastCheckedPos).setSelected(false);
}

lastChecked = cb;
lastCheckedPos = clickedPos;
}
else
lastChecked = null;

fonts.get(clickedPos).setSelected(cb.isChecked);
}
});
}
}


Related Topics



Leave a reply



Submit