i have a BaseAdapter for my ListView inside a fragment that looks like this:
public class SelectionMucListAdapter extends BaseAdapter {
private LayoutInflater inflater = null;
Typeface titleFace;
ArrayList<UsersData> innerList = new ArrayList<UsersData>();
public SelectionMucListAdapter(ArrayList<UsersData> users) {
inflater = (LayoutInflater) mainActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
titleFace = Typeface.createFromAsset(mainActivity.getAssets(), "fonts/bradybun.ttf");
innerList = users;
}
@Override
public int getCount() {
return innerList.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int id) {
return id;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.muc_list_item, null);
viewHolder = new ViewHolder();
viewHolder.image = (ImageView)convertView.findViewById(R.id.item_image);
viewHolder.check = (CheckBox)convertView.findViewById(R.id.cb_choose_user);
viewHolder.title = (TextView)convertView.findViewById(R.id.item_text_1);
viewHolder.rating=(RatingBar)convertView.findViewById(R.id.item_text_2);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder)convertView.getTag();
}
viewHolder.title.setTypeface(titleFace);
Bitmap avatar = innerList.get(position).getUserAvatar();//UsersManager.getInstance().getUsers().get(position).getUserAvatar();
if(avatar != null)
viewHolder.image.setImageBitmap(avatar);
viewHolder.title.setText(innerList.get(position).getUserName());
viewHolder.rating.setRating((float)Double.parseDouble(innerList.get(position).getRating()));
viewHolder.check.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton cb, boolean isChecked) {
if(cb.isChecked()) {// if this item is checked then add to list
Log.v("CheckBox", "pos: "+position+" checked");
if(!choices.contains(innerList.get(position))) {
choices.add(innerList.get(position));
}
} else {// if its unchecked then remove from list if exist
Log.v("CheckBox", "pos: "+position+" checked");
if(choices.contains(innerList.get(position))) {
choices.remove(innerList.get(position));
}
}
isChecked = cb.isChecked();
}
});
viewHolder.check.setTag(position);
return convertView;
}
}
static class ViewHolder{
ImageView image;
CheckBox check;
TextView title;
RatingBar rating;
}
class CheckState{
boolean isChecked;
UsersData usersData;
public UsersData getUsersData() {
return usersData;
}
public void setUsersData(UsersData usersData) {
this.usersData = usersData;
}
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean isChecked) {
this.isChecked = isChecked;
}
}
i have 20 list items, and the problem is that when i checked first 2 items for example at index [0] and [1], somehow it also checked automatically other items at index [9] and [10] when i scroll down the list. same case happened if i checked other items and it will checked repeatedly with the same pattern every time i scroll down the list.
i actually dont know what's happening, so i want to ask if anyone here can stop this messy. Thank you!
I'm currently using solution provided here: ListView with CheckBox Scrolling Issue
it works for me and i change my adapter class like this:
i use 2 arraylists to keep the data: first, for all data and the second for the data that the user currently searching. so, while the user is typing to search by keywords the check state are passed between the first and the second arraylist resulting in the persistence checked items no matter what position they're.
but thanks for raghunandan, your answer is my corner stone to reach a better solution!
In addition to @Raghunandan answer, Android re-uses the views in the listview while scrolling such that when you scrollthe list view, the last view which went out of the screen is the next view which will come into the screen from the other side, so that if 1 and 2 are checked and 9 and 10 will be checked after scrolling this probably means that there are 8 items displayed at the same time on the screen such that the ninth item android system used the view of the first one so it will checked.
Your Custom Adapter must implement
CompoundButton.OnCheckedChangeListener
. Use aSparseBooleanArray.
Then
Then use the checked state to set text to check box
Discussion on the topic @
https://groups.google.com/forum/?fromgroups#!topic/android-developers/No0LrgJ6q2M
Example:
Use a
ViewHolder
. The below example does not use a View Holder.There is a Button at the bottom of the screen. When you check the check boxes items of the checked rows are displayed in a toast when you click the button at the bottom.
Use the below and modify according to your requirements.
The tricky tip here is using a boolean array with size() = number of listview items. The purpose is marking which item is selected, which is not. When you check an item, update its state following its position. Hope this help you. :)
i think this is useful for you in my xml i am taking textview and check box.use getView() method like that i have implemented and use bean class for communication between activity and adapter.
}