问题
Recently, I encountered a problem with a ListView. In it there is a list of checkboxes. The checked items are fed to the calling Activity that starts my ListActivity with startActivityForResult. If there were any checked items previous to calling the ListActivity, those items are passed to it so the user can edit his previous selection rather than starting over. First time around everything is fine. But when I want to alter the selection by calling the ListActivity again, the first checkbox in the list looks like it is checked if any of the items in the list are checked. In fact it is not recognized as checked, i.e. the code checking the already selected items doesn't fire when it processes the first item and after saving the selection again, the first item is not part of the list returned to the parent as long as it has not explicitly been checked (via unchecking and then checking it again).
When I searched for this problem, I found out that the first item of a ListView receives focus, so I tried
listView.setItemsCanFocus(false);
to no effect. Actually I would have been surprised if it had worked, because the item is only checked when there is a non-empty selection. As I found no question that addresses my problem, I boiled it down to an example that still produces the effect described. Sorry for all the code, but I'm at a total loss at what to look for, so I don't know how I could describe my problem by posting less.
onCreate and onActivityResult of the calling activity:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
listItems = new ArrayList<String>();
list = (TextView) findViewById(R.id.list);
list.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Bundle extras = new Bundle();
extras.putStringArrayList("item_list", listItems);
Intent i = new Intent(Main.this, CheckBoxListActivity.class);
i.putExtras(extras);
startActivityForResult(i,1);
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
Bundle extras = new Bundle();
extras = intent.getExtras();
String[] strings = extras.getStringArray("item_list");
String text = "";
listItems.clear();
for ( String item : strings ) {
text = text + item + ", ";
listItems.add(item);
}
if ( text.length() != 0 ) {
text = text.substring(0, text.length() - 2);
} else {
text = "(nothing here)";
}
list.setText(text);
}
onCreate() and finish() in the ListActivity:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.checkbox_list);
listView = getListView();
save = (Button) findViewById(R.id.save_button);
save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(LOG_TAG, "save button clicked");
finish();
}
});
ArrayList<String> itemList = new ArrayList<String>();
itemList.add( "foo" );
itemList.add( "bar" );
itemList.add( "baz" );
itemList.add( "qux" );
itemList.add( "quux" );
checkedItems = getIntent().getExtras().getStringArrayList("item_list");
ArrayAdapter<String> arrayAdapter = new ItemsAdapter(this, R.layout.checkbox_list, itemList);
listView.setAdapter(arrayAdapter);
}
@Override
public void finish() {
Bundle extras = new Bundle();
String[] stringArray = new String[checkedItems.size()];
for ( int i = 0; i < checkedItems.size(); i++) {
stringArray[i] = checkedItems.get(i);
}
extras.putStringArray("item_list", stringArray);
Intent mIntent = new Intent();
mIntent.putExtras(extras);
setResult(RESULT_OK, mIntent);
super.finish();
}
And the ArrayAdapter:
private class ItemsAdapter extends ArrayAdapter<String> {
public ItemsAdapter(Context context, int textViewResourceId, List<String> items) {
super(context, textViewResourceId, items);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.checkbox_list_row, null);
}
String entry = getItem(position);
v.setTag(entry);
fillText(v, R.id.checkbox, entry);
return v;
}
private void fillText(View v, int id, String text) {
Log.i(LOG_TAG, "this is fillText, our text is: " + text);
CheckBox checkBox = (CheckBox) v.findViewById(id);
if ( checkedItems.contains(text)) {
Log.i(LOG_TAG, "item has to be checked");
checkBox.setChecked(true);
}
checkBox.setText(text == null ? "" : text);
checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton cb, boolean isChecked) {
String tag = (String) cb.getTag();
if (cb.isChecked()) {
// add item to set of checkedItems
if ( !checkedItems.contains(tag)) {
checkedItems.add(tag);
Log.i(LOG_TAG, "checkedItems: " + checkedItems.toString());
}
} else {
// remove item from set of checkedItems
if ( checkedItems.contains(tag)) {
checkedItems.remove((String) cb.getTag());
Log.i(LOG_TAG, "checkedItems: " + checkedItems.toString());
}
}
}
});
}
}
回答1:
You need to be aware that the checkbox from a convert view might be checked. You need to uncheck it if the text is not in the list.
private void fillText(View v, int id, String text) {
Log.i(LOG_TAG, "this is fillText, our text is: " + text);
CheckBox checkBox = (CheckBox) v.findViewById(id);
if ( checkedItems.contains(text)) {
Log.i(LOG_TAG, "item has to be checked");
checkBox.setChecked(true);
} else {
checkBox.setChecked(false);
}
来源:https://stackoverflow.com/questions/10294174/android-listview-of-checkboxes-always-checks-first-item-if-any-item-is-checked