I'm using a ListView with CheckBox, but as most of you know, when you roll down the scroll, a checked CheckBox gets unchecked as you roll up back the scroll. So i've been reading and i found out that you can pass (using getView) the id of the CB to the position parameter of getView to save the CheckBox state!
But i can't use getView with SimpleCursorAdapter, can i? Because i'm using bindView!
Thanks
What is happening is recycling. 7 rows fit in your screen and when you scroll down, the top one is being recycled for the new one at the bottom. What you should do is to save the states of the checkboxes.
Here is a good solution to a similar problem:
https://github.com/commonsguy/cw-android/tree/master/FancyLists/RateList
I managed to get the checkbox state restored after i scroll up/down using setViewBinder (saw it in another answer):
mAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if(columnIndex==4) {
cb=(CheckBox)view;
cb.setChecked(cursor.getInt(4)==0? false:true);
return true;
}
return false;
}
});
But still something weird happens, the CheckBox is being recycled after 7 or 8 positions. If i check the first CheckBox and theres more than 10 positions/rows, the 8th is also checked, same happens when i check the last one, 8 positions up there will be a checked CheckBox.
Any thoughs? Ideias? Help!
Related
I have a scrollable listview that has 2 textViews, 3 imageButtons and 1 checkBox in each row.
In the Header of the listView, I have a delete button just above the column containing all the checkboxes of the listView.
I have to perform the delete operation of objects in the listView when 2 or more checkBoxes are checked randomly by scrolling the listView and thereafter the delete button at the top is clicked.
But the problem is that i am not getting the correct poition of the checkbox that was selected. Moreover, sometimes i get the correct position but still the object to be deleted passed is wrong. Hence the entire functionality is affected maybe due to the scrolling nature of the list.
Should i take the position in the holder of the adapter class and also bind the state of the checked or unchecked checkbox with my object.
And should I use checkBox.setOnCheckedChangeListener() or deleteButton.setOnClickListener().
If i use the latter one, then how to get all the corresponding objects of the list whose checkboxes were checked before pressing the delete button?
And where should all the related code be placed..in the listAdapter class or in the activity?
Please help me find a solution to this problem..
first of all in your getView() method you should set a specific Tag to each checkBox. For example: check1.setTag(position) then you should implement both OnCheckBoxChangeListener for your checkBoxes and OnClickListener for your delete button. As you know setting of onCheckBoxChangeListner have to be in getView() method. Then you add positions of list that their checkBox is checked to the a ArrayList with the help of getTag() method of chechBoxes in onCheckedChanged() method.
Try getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {}
I have a problem with my customized Listview with 2 TextViews and a CheckBox in each item, the problme is when scrolling the Listview, the checked items get unchecked randomly and vice versa, can anyone help to define a customized Adapter to solve this problem, i'll be so thankful
I had the same problem and I solved as follows:
I have a boolean variable isCheckedByUser. In the adapter, everytime I do something with the checkbox, i set this variable to false first, do all the things I have to with the checkbox, and set the variable to true again. Then, in the method onCheckedChanged I check if this variable is true, if so, means that the user wanted to modify the state, so I do whatever its needed with the checkbox.
In fact, this problem is not so "random". The listview reuses the cells, so that's why for you seems like the checkboxes are unchecked randomly.
Check that you correctly recycle the convertView param in getView.
If the view was already in use, ensure the checked state fits with the new item represented.
I added a button in a listview item, and after the button is clicked, I want the button is disabled. I used the below setOnClickListener for my button in the custom adapter, but the problem is when i clicked on a button, the button of another list item will also be disabled. For example, when I clicked the button of item 1, the button of item 1 then is disabled, but the item 4's button will also be disabled at the same time although i didn't click on it.
And also, when I scroll up and down, all item's button just enable and disable randomly.
Anyone know why is this happening?
holder.viewBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.viewBtn.setEnabled(false);
showInfo();
} });
I was so frustrated when I first faced this problem!
The problem here is that the listview just doesn't remember the state of the button. Dunno if it is a bug but anyways I needed a way out and this is what I did.
I believe you are using a custom adapter with a viewholder. Means you are on the right path. You need to keep an array of booleans whose size is equal to the number of items in your list. in your btnClick() set the state of the item in the array.
Now everytime you scroll, or do soemthing that makes the list redraw, getView() is called. Put a check in your getView() for the items state and enable/disable it. One more thing, Make sure you implement both if{} and else{} for the check.
if(checked){
holder.viewBtn.setEnabled(false);
}else{
holder.viewBtn.setEnabled(true);
}
if you don't do this you'll see weird behaviours. One more thing if you are using the
if(convertview == null){
//create the holder
}else{
convertview = getTag();
}
method, make sure you populate the state after the above step.
I have not seen your implementation but I had to pop up a button in the item and then delete the item from the list using it. So I had to take extra care for maintaining the state.
So be careful about the states once the underlying data has changed.
Sorry about the long post but the problem is such :(
I found a link that has the solution in a basic format
This is happening because ListView reuses Views in an erroneous manner. Either implement your own ListAdapter without View reuse or file a bug report with Google
I've set up a ListView that contains a Checkbox in each row (along with a TextView). For some reason, when I "check" one of the boxes, it seems to "check" whichever box is opposite in the ListView (i.e. when selecting the top box, the bottom checkbox becomes selected while the top remains unchecked.
I realize there isn't any code here to work with, but I was just wondering if this is a general problem? If not, I can try to post some code. Thanks!
Views are recycled in a ListView. That's why some are checked when you think shouldn't be.
Here's the deal: The checkbox has no idea which item in your adapter it represents. It's just a checkbox in a row in a ListView. You need to do something to "teach" the rows which item in your data set they are currently displaying. So, instead of using something as simple as a String array as the data for your adapter, create a new model object that stores the state of the checkbox in it. Then, before you return the row in getView(), you can do something like:
//somewhere in your class
private RowData getData(int position) {
return(((MyAdapter)getListAdapter()).getItem(position));
}
//..then in your adapter in getView()
RowData object = getModel(position);
if(object.isChecked()) {
myCheckbox.setChecked(true);
} else {
myCheckbox.setChecked(false);
}
//then retun your view.
I've got a ListView with a custom BaseAdapter. The list items contain CheckBoxes that need to represent a property from a database.
I use CheckBox.setOnCheckedChangeListener with a new OnCheckedChangeListener to detect changes, so I can change the database based on the current state of the CheckBox. Pretty straightforward stuff so far.
However, when scrolling further down the list, previously checked CheckBoxes get unchecked. I suspect this happens as soon as the views are recycled (I'm using the convertView/ViewHolder technique).
How can I stop this? What's going wrong?
Thanks in advance.
Edit: To make things a bit clearer, the problem is that recycling views somehow calls OnCheckedChangeListener#onCheckedChanged(buttonView, isChecked) with isChecked == false.
Apparently the problem was that, by getting the checkbox using convertView.findViewById(), the onCheckedChangeListeners were still intact if the view was recycled. Calling checkbox.setOnCheckedChangeListener(null) did the trick.
Use a boolean array to store the checked state of each list item, record the changes inside setOnCheckedChangeListener(), then call setChecked() after setOnCheckedChangeListener().