Android Click on listItem will check the wrong checkbox

I created my own ListView by extending SimpleCursorAdapter. The result is IMAGE + CheckedTextView (text + checkbox).

When I click on an element for a long time, everything works fine - I get the correct identifier and details of the clicked element.

The problem occurs when I try to mark an item as checked, but it checks the wrong flag.

For example: I have 9 items in my list, sorted 1-9. if I click on listItem 1, check the box in line 9. if I click on item 4, the box in line 6 is checked, and if I click on the middle line, it is checked.

It’s clear that I missed something :) Remember, when I click on the line for a long time (contextMenu opens), everything works fine.

This is the listener:

lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { CheckedTextView markedItem = (CheckedTextView) view.findViewById(R.id.btitle); if (!markedItem.isChecked()) { markedItem.setChecked(true); } else { markedItem.setChecked(false); } } }); 

Appreciate any help!

Let me know if you need me to post more code.

Thank!

btw, If I press more than one ... THE PARTY will continue ... there is no obvious order ...

EDIT: Adapter Code

 public class ImageCursorAdapter extends SimpleCursorAdapter { private Cursor c; private Context context; private String url; private TextView bUrl; public ImageCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { super(context, layout, c, from, to); this.c = c; this.context = context; } public View getView(int pos, View inView, ViewGroup parent) { View v = inView; if (v == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = inflater.inflate(R.layout.image_list, null); } this.c.moveToPosition(pos); final TextView bTitle = (TextView) v.findViewById(R.id.btitle); String bookmark = this.c.getString(this.c.getColumnIndex(Browser.BookmarkColumns.TITLE)); byte[] favicon = this.c.getBlob(this.c.getColumnIndex(Browser.BookmarkColumns.FAVICON)); if (favicon != null) { ImageView iv = (ImageView) v.findViewById(R.id.bimage); iv.setImageBitmap(BitmapFactory.decodeByteArray(favicon, 0, favicon.length)); } bTitle.setText(bookmark); return (v); } } 
+8
android listview checkedtextview
Oct 24 2018-10-10
source share
1 answer

Myra is right - the problem is how the ListView is reusing your views. This is not like 9 instances of a CheckedTextView object, one per view. Instead, there is one that is reused on all lines. Thus, you cannot rely on a CheckedTextView object to maintain the validation state of an element. You will need an additional data structure to check if a given string is checked. For example,

 ArrayList<Boolean> checkedStates = new ArrayList<Boolean>(); 

If the ith element is true, if the ith string ith to be checked. Then in your itemClickListener:

 lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { boolean currentlyChecked = checkedStates.get(position); checkedStates.set(position, !currentlyChecked); // Refresh the list } }); 

Then in your view code:

 public View getView(int pos, View inView, ViewGroup parent) { View v = inView; if (v == null) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = inflater.inflate(R.layout.image_list, null); } this.c.moveToPosition(pos); final TextView bTitle = (TextView) v.findViewById(R.id.btitle); String bookmark = this.c.getString(this.c.getColumnIndex(Browser.BookmarkColumns.TITLE)); byte[] favicon = this.c.getBlob(this.c.getColumnIndex(Browser.BookmarkColumns.FAVICON)); if (favicon != null) { ImageView iv = (ImageView) v.findViewById(R.id.bimage); iv.setImageBitmap(BitmapFactory.decodeByteArray(favicon, 0, favicon.length)); } bTitle.setText(bookmark); // Change the state of the checkbox to match that of the row checked state. // This check box item is reused for every row, so we need to reset its state each // time the row is rendered. CheckedTextView markedItem = (CheckedTextView) view.findViewById(R.id.btitle); markedItem.setChecked(checkedStates.get(pos)); return (v); } 

This should solve your problem. An alternative approach would be to move the logic of whether the string is checked or not to the domain object that the string represents. That would be my advantage.

+11
Oct 24 '10 at 23:49
source share



All Articles