Android ListView of CheckBoxes always checks first item if any item is checked

依然范特西╮ 提交于 2019-12-25 05:16:26

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!