ListView multichoice implementation only one click more than one selection

380 views Asked by At

I try to implement a listview multichoice. I achive display all my contact in a listview with checkBox item. My problem is that when check ONLY one item there is lots of element are being cheked. Could you please help?

public class SelectNewGroupChatMembers extends ListFragment implements
        LoaderCallbacks<Cursor>, OnItemClickListener {
/** Defines a tag for identifying log entries */
private static final String TAG = "SelectNewGroupChatMembers";
/** The main query adapter */
private ContactsAdapter mAdapter;
/** ListView which will display contacts */
ListView mListView;
/** Fragments require an empty constructor. */
public SelectNewGroupChatMembers() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Create the main contacts adapter
    mAdapter = new ContactsAdapter(getActivity());
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_list, container, false);
    mListView = (ListView)view.findViewById(android.R.id.list);
    return view;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Log.i(TAG, "clicked");
    mListView.setAdapter(mAdapter);
    mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    mListView.setOnItemClickListener(this);     
    // Initialize the loader, and create a loader identified by ContactsQuery.QUERY_ID
    getLoaderManager().initLoader(ContactsQuery.QUERY_ID, null, this);
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
        long id) {
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle savedInstanceState) {
    // If this is the loader for finding contacts in the Content Provider
    if (id==ContactsQuery.QUERY_ID) {
        Uri contentUri = ContactsQuery.CONTENT_URI;
        Log.i(TAG, contentUri.toString());
        // Create a new CursorLoader with the following query parameters.
        return new CursorLoader(getActivity(),
                contentUri,
                ContactsQuery.PROJECTION,
                ContactsQuery.SELECTION,
                null,
                ContactsQuery.SORT_ORDER);
    }
    Log.i(TAG, "onCreateLoader - incorrect ID provided ( "+ id +" )");
    return null;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    // This swaps the new cursor into the adapter.
    if (loader.getId() == ContactsQuery.QUERY_ID) {
        Log.i(TAG,cursor.toString());
        // The asynchronous load is complete and the data
        // is now available for use. Only now can we associate
        // the queried Cursor with the SimpleCursorAdapter.
        mAdapter.swapCursor(cursor);
    }
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    if (loader.getId() == ContactsQuery.QUERY_ID) {
        // When the loader is being reset, clear the cursor from the adapter.
        // This allows the cursor resources to be freed.
        mAdapter.swapCursor(null);
    }
}

private class ContactsAdapter extends CursorAdapter {
    private LayoutInflater mInflater;
    public ContactsAdapter(Context context) {
        super(context, null, 0);
        // Stores the inflater for the later use
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
        // Inflate the list item layout
        final View itemLayout = 
                mInflater.inflate(R.layout.fragment_select_new_group_chat_members, viewGroup, false);
        // Use ViewHolder design pattern to store each view resource.
        // This allows bindView() to retrieve stored references instead of 
        // calling findViewById for each instance of the layout.
        final ViewHolder holder = new ViewHolder();
        holder.contactName = (TextView)itemLayout.findViewById(R.id.userName);
        holder.contactNo = (TextView)itemLayout.findViewById(R.id.userInfo);
        // Store the resourceHolder instance in Layout.
        // This makes resourceHolder available to bindView
        // and other methods that receive a handle to the item view
        itemLayout.setTag(holder);
        return itemLayout;
    }
    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        // Get handles to individual view sources
        final ViewHolder holder = (ViewHolder) view.getTag();
        final String contactName = cursor.getString(ContactsQuery.DISPLAY_NAME);
        final String contactNumber = cursor.getString(ContactsQuery.PHONE_NUMBER);
        holder.contactName.setText(contactName);
        holder.contactNo.setText(contactNumber);
    }
    private class ViewHolder {
        public TextView contactName, contactNo;
    }
}

public interface ContactsQuery {
    // This query ID will be used in Loader
    final static int QUERY_ID = 1;
    // A content URI for the Contacts table
    final static Uri CONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
    final static String SELECTION = null;
    final static String SORT_ORDER = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME;
    final static String [] PROJECTION = {
        ContactsContract.CommonDataKinds.Phone._ID,
        ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY,
        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Phone.NUMBER,
        SORT_ORDER,
    };
    final static int ID = 0;
    final static int LOOKUP_KEY = 1;
    final static int DISPLAY_NAME = 2;
    final static int PHONE_NUMBER = 3;
    final static int SORT_KEY = 4;
}
}

My layout file is as below:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="6dip" >

<ImageView
    android:id="@+id/userImage"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_marginRight="6dip"
    android:src="@drawable/ic_action_user" />

<CheckBox
    android:id="@+id/checkBox"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_alignBottom="@id/userImage"
    android:layout_alignTop="@id/userImage"
    android:layout_alignParentRight="true"
    android:focusable="false"
    android:gravity="center" />

<TextView
    android:id="@+id/userName"
    android:layout_alignTop="@id/userImage"
    android:layout_toRightOf="@id/userImage"
    android:layout_toLeftOf="@id/checkBox"
    android:layout_width="wrap_content"
    android:layout_height="25dp"
    android:gravity="center_vertical"
    android:text="ContactName"
    android:textStyle="bold" />

<TextView
    android:id="@+id/userInfo"
    android:layout_alignBottom="@id/userImage"
    android:layout_toRightOf="@id/userImage"
    android:layout_toLeftOf="@id/checkBox"
    android:layout_width="wrap_content"
    android:layout_height="25dp"
    android:gravity="center_vertical"
    android:text="UserInfo" />

</RelativeLayout>

At final my code is like above. This code queries contacts and display them on a listview which including a checkBox. I tried some different code snippets but with all my tries i get same result. My problem is that when check ONLY one item there is lots of element are being cheked. Could you help please?

1

There are 1 answers

1
Vab On

I don't see where you are manipulating the checkbox on item click in this code. Ideally onItemClick you should get the Holder object out of the view tag by calling view.getTag. In your holder there is a checkbox view instance so you can enable the checkbox there. So something like this on your onItemClick method.

Holder holder = (Holder) view.getTag();
holder.checkbox.setChecked(!checkbox.isChecked());