10

Edit: Okay, I found a solution. Don't know that it's the proper solution, but it does work correctly. Added to the code below.

I'm trying to allow a user to select a number of directories from a checklist, and return them upon clicking a "Submit" button. Here's a snippet of my code. It populates the ListView with all the directories on /sdcard/, and for the initial selection (of however many I pick) when I submit, the log shows the correct choices returned. However, if I uncheck an item, and click "Submit" again, it still shows as if all are selected. Do I need to write a handler to uncheck an item? I thought that was taken care of by the choiceMode selection? Thanks!

private SparseBooleanArray a;    
directoryList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, directoryArray));
    submitButton = (Button)findViewById(R.id.submit_button);
    submitButton.setOnClickListener(new OnClickListener()
        {
        @Override
        public void onClick(View v)
        {
            a = new SparseBooleanArray();
            a.clear();
            a = directoryList.getCheckedItemPositions();

            for (int i = 0; i < a.size(); i++)
            {
                //added if statement to check for true. The SparseBooleanArray
                //seems to maintain the keys for the checked items, but it sets
                //the value to false. Adding a boolean check returns the correct result.                    
                if(a.valueAt(i) == true)
                    Log.v("Returned ", directoryArray[a.keyAt(i)]);

            }                
        }
    });
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274

4 Answers4

3

Did some more debugging and found a solution that worked for me. Edited into code above. For some reason, the SparseBooleanArray doesn't empty itself; it maintains the keys of the boxes that have been checked. When getCheckedItemPositions() is called, however, it sets the VALUE to false. So the key is still in the returned array, but it has a value of false. Only the checked boxes will be marked with a value of true.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
3

I know you found a solution that works for you, but the cleaner and simpler solution that will probably work most of the time is this (I want to persist all the ids of the elements selected):

(in my ListActivity):

SparseBooleanArray selectedPos = getListView()
        .getCheckedItemPositions();

ListAdapter lAdapter = getListAdapter();
List<Long> ids = new ArrayList<Long>();
for (int i = 0; i < lAdapter.getCount(); i++) {
    if (selectedPos.get(i)) {
        ids.add(lAdapter.getItemId(i));
    }
}
ansjob
  • 175
  • 7
1

didn't mean to do this as an answer but i had to expand on what you did to do multi select. Why did you do a field variable for your selections? i just did local SparseBooleanArray...

public class NaughtyAndNice extends ListActivity {
TextView selection;
String[] items={"lorem","ipsum", "dolor", "sit", "amet",
        "consectetuer", "adipisc", "jklfe", "morbi", "vel",
        "ligula", "vitae", "carcu", "aliequet"};

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_multiple_choice,items));
           selection = (TextView)findViewById(R.id.selection);
    this.getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}

public void onListItemClick(ListView parent, View view, int position, long id){
    SparseBooleanArray choices = parent.getCheckedItemPositions();
    StringBuilder choicesString = new StringBuilder();
    for (int i = 0; i < choices.size(); i++)
    {
    //added if statement to check for true. The SparseBooleanArray
    //seems to maintain the keys for the checked items, but it sets
    //the value to false. Adding a boolean check returns the correct result.                    
        if(choices.valueAt(i) == true)
            choicesString.append(items[choices.keyAt(i)]).append(" ");

    } 
    selection.setText(choicesString);
}
}

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
JDPeckham
  • 2,414
  • 2
  • 23
  • 26
  • it seems horribly inefficient to do the for loop and then inside the for loop do a keyAt... how bad does keyAt run? oh well – JDPeckham Dec 07 '10 at 04:45
  • I'm not understanding the difference in this code...it appears to be functionally identical to mine. – Kevin Coppock Dec 07 '10 at 05:03
  • Oh nevermind, I missed your question. There was no real reason to doing a class variable for the SBA, I was just new to Java and Android and did it stupidly. :) – Kevin Coppock Dec 07 '10 at 05:43
1

No need to use SparseBooleanArray choices = parent.getCheckedItemPositions();

StringBuilder is enough for this.

Kai
  • 38,985
  • 14
  • 88
  • 103
nipun
  • 11
  • 1