PhillipOReilly
PhillipOReilly

Reputation: 609

How to get setMultiChoiceItems checkboxes in dialogs to update when you use a Sqlite Cursor

When implementing setMultiChoiceItems with a cursor, you have to specify an isCheckedColumn.

The problem, as articulated on other sites, is that when users select an item from the list the checkbox does not update. Some have suggested updating the SqLite table each time a user selects an item, but this did not work in my application. Here is the solution I came up with.

Upvotes: 3

Views: 3033

Answers (1)

PhillipOReilly
PhillipOReilly

Reputation: 609

This is what I came up with:

    @Override
public Dialog onCreateDialog(Bundle savedInstanceState) {

    int myDialogChoice = getArguments().getInt("whichDialog");
    mSelectedItems = new ArrayList();  // Where we track the selected items
    mCurrentFavoritesSelection = new ArrayList();

    myDataBaseAdapter = new AthleteDbAdapter(getActivity());
    //      int myAthleteId;
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

    switch(myDialogChoice) {
        case Select_From_Favorites:

            myCursorFromSqLite = myDataBaseAdapter.fetchAllFavorites(getActivity());

            // You need a Primative Boolean Array to specify which items were selected last time.
            boolean[] booleanPrimativeArray = new boolean[myCursorFromSqLite.getCount()];

            final ArrayList mArrayListOfIDs             =   new ArrayList();
            ArrayList<Boolean> myBooleanList = new ArrayList<Boolean>();

            // This array will be the choices that appear in the Dialog.
            ArrayList<String> mArrayListOfNames =   new ArrayList<String>();

            myCursorFromSqLite.moveToFirst();
            /* Populate Arrays
             *
             */
            int iCount = 0;

            while(!myCursorFromSqLite.isAfterLast()) {
                // put _id's from SqLite data into an array.
                mArrayListOfIDs.add(Integer.valueOf(
                                                    myCursorFromSqLite.getString(myCursorFromSqLite.getColumnIndex(KEY_ROWID))));


                // put series of booleans into Primative Array depending upon whether user selected them last time.
                if(Integer.valueOf(myCursorFromSqLite.getString(myCursorFromSqLite.getColumnIndex("checked"))) == 1){
                    booleanPrimativeArray[iCount] = true;
                    mSelectedItems.add(
                                       Integer.valueOf(myCursorFromSqLite.getString(myCursorFromSqLite.getColumnIndex(KEY_ROWID)))
                                       );
                    // I kept track of what selections from last time were.
                    mCurrentFavoritesSelection.add(
                                                   Integer.valueOf(myCursorFromSqLite.getString(myCursorFromSqLite.getColumnIndex(KEY_ROWID)))
                                                   );
                } else booleanPrimativeArray[iCount] = false;
                iCount++;
                mArrayListOfNames.add(myCursorFromSqLite.getString(myCursorFromSqLite.getColumnIndex("fullName")));
                myCursorFromSqLite.moveToNext();
            }

            // Change the ArrayList of names to a Char Sequence
            CharSequence[]  charSeqOfNames = mArrayListOfNames.toArray(new CharSequence[mArrayListOfNames.size()]);
            try{
                myCursorFromSqLite.close();
            } catch (Throwable t) {
                Log.e(APP_TAG,"Error closing myCursorFromSqLite Cursor " + t);
            }
            builder.setTitle(R.string.pick_athletes)

            .setMultiChoiceItems(charSeqOfNames, booleanPrimativeArray,
                                 new DialogInterface.OnMultiChoiceClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which,
                                    boolean isChecked) {
                    if (isChecked) {
                        // If the user checked the item, build an array containing the selected items _id's.
                        mSelectedItems.add((Integer) mArrayListOfIDs.get(which));

                    } else if (mSelectedItems.contains((Integer) mArrayListOfIDs.get(which))) {
                        // Else, if the user changes his mind and de-selects an item, remove it 
                        mSelectedItems.remove((Integer) mArrayListOfIDs.get(which));
                    }
                }
            })
            // Set the action buttons
            .setPositiveButton(R.string.pullathletesbutton, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int id) {
                    // User clicked OK, so save the mSelectedItems results somewhere
                    // or return them to the component that opened the dialog
                    Log.d(APP_TAG,"Call something");

                    mListener.onDialogPositiveClick(PickListDialog.this, mSelectedItems, mCurrentFavoritesSelection);
                }
            })
            .setNegativeButton(R.string.cancelbutton, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int id) {

                }
            });

This worked well. The user can change his mind without affecting the underlying database and the checkmarks update properly. Once the user has finalized his choices, he hits the "positive" button and the database is updated.

Upvotes: 2

Related Questions