0

I have a problem in my custom listview which seems to be showing wrong items selected when i search content of my list view. (check screenshots below you will understand)

enter image description here enter image description here enter image description here

  1. searched with name aa and selected two rows(AABBCCC and AABC)

  2. I have searched with Na but didn't select the rows (Jana and Nathan). But it is showing as selected.

  3. Removed all the search items, and i didn't select any rows after removing search. It is supposed to show two rows( AABBCC and AABC), but it is showing up the wrong row Jana.

I don't how to override the above behaviour. I have to make contact as checkable based on _rowid not the position.

Which class will keep track of the items selected in the list ? How to override the above behaviour??

It has two rows Name and number. I have customized my layout(code below) which implements checkable.

Search Name(EditText)        [Done Btn]
---------------------------------------
Contact_name_1         
Phone_no
---------------------------------------
Contact_name_2         
Phone_no2
---------------------------------------
Contact_name_3         
Phone_no3
---------------------------------------

Custom layout with checkable items..

public class CustomCheckableLists extends RelativeLayout implements Checkable {

 private Checkable mCheckable;

public CustomCheckableLists(Context context) {
    super(context);
}

public CustomCheckableLists(Context context, AttributeSet attrs)
{
    super(context,attrs);
}

public boolean isChecked() {
    return mCheckable == null ? false : mCheckable.isChecked();
    //return false;
}

public void setChecked(boolean checked) {
    if(mCheckable != null)
        mCheckable.setChecked(checked);


}

public void toggle() {
     if(mCheckable != null)
            mCheckable.toggle();
}

@Override
protected void onFinishInflate() {
    super.onFinishInflate();

    //Find items id..

    Log.w("onFinishInflate","onFinishInflate");

    // Find Checkable child
    int childCount = getChildCount();
    for (int i = 0; i < childCount; ++i) {
        View v = getChildAt(i);
        if (v instanceof Checkable) {
            mCheckable = (Checkable) v;
            break;
        }
    }
}

Custom XML Layout

<CustomCheckableLists
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:gravity="center_vertical" 
      android:orientation="horizontal"
    >

    <TextView 
    android:id="@+id/id"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="name" 
    android:visibility="invisible"
    />

    <TextView 
    android:id="@+id/text1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="nuoo" 
    />

    <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/phonenu"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:checkMark="?android:attr/textCheckMark"
    android:gravity="center_vertical"
    android:paddingLeft="3dp"
    android:paddingRight="6dp"
    android:paddingTop="25dip"
    />

</CustomCheckableLists>

Contact Activity Class

    String[] columns = new String[] {
            ContactsContract.Contacts._ID,
            ContactsContract.Contacts.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER
    };

    int[] to = new int[] {
            R.id.id,
            R.id.text1,
            R.id.phonenu
    };

    dataAdapter = new SimpleCursorAdapter(this, R.layout.custom_checkable_item, cursor, columns, to);
    listView.setAdapter(dataAdapter);

any help is appreciated. Thanks in advance.

Edit

Whenever user searches for any name, a query has been formed to return the searched result. code below

 searchNameOrNumber = (EditText) findViewById(R.id.searchText);
    searchNameOrNumber.addTextChangedListener(new TextWatcher() 
    {
        public void onTextChanged(CharSequence searchterm, int start, int before, int count) {
            Log.w("Text Searched.. ", " " + searchterm);
            dataAdapter.getFilter().filter(searchterm.toString());
            //dataAdapter.notifyDataSetChanged();
        }

        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
        }
        public void afterTextChanged(Editable s) {
        }
    });

    dataAdapter.setFilterQueryProvider(new FilterQueryProvider() {
        public Cursor runQuery(CharSequence constraint) {
            Log.w("Searched Query..,", constraint.toString());
            );


            return getSearchedContacts(constraint.toString());
        }
    });


public Cursor getSearchedContacts(String inputText)
{
    Log.w("inputText",inputText);
        Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        String[] projection = new String[] {
                ContactsContract.Contacts._ID, 
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                   ContactsContract.CommonDataKinds.Phone.NUMBER
        };
        String selection = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " like '%" + inputText + "%'";

        Cursor people = getContentResolver().query(uri, projection, selection, null, null);

        int indexName = people.getColumnIndex(StructuredName.DISPLAY_NAME);
        int indexNumber = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
        int idIdx = people.getColumnIndexOrThrow(PhoneLookup._ID);

        if(!people.moveToFirst())
        {
            Log.w("No Cursor.., ","No cursor.., Cursor is empty..");
        }

        do {
            String id = people.getString(idIdx);
            String name   = people.getString(indexName);
            String number = people.getString(indexNumber);
            // Do work...
        } while (people.moveToNext());

        return people;


}
swastican
  • 257
  • 1
  • 2
  • 15

1 Answers1

1

You need to create a custom Adapter and track the checked items there. The reason you're seeing this behavior is because the SimpleCursorAdapter is recycling the views, and doesn't know how to deal with the checked state, and just sets the text labels, leaving the checked state as it was before.

Another way to see this behavior is having more than a screenful of items, check some and then scroll and you would also notice that random items get checked/unchecked as you scroll.

You can view a complete sample of how to get this working in this answer.

If you're using this for searching then every time you filter you will have to clear the list of checked positions.

Community
  • 1
  • 1
dmon
  • 30,048
  • 8
  • 87
  • 96