Search code examples
androidandroid-listviewactionbarsherlock

Why does isItemChecked() return true when in ActionMode?


I've set up an ActionMode callback for use as the contextual ActionBar (CAB) within an ActionBarSherlock using project.

I'm trying to set up multiple select so that I can delete multiple items in a ListView.

I noticed while debugging, when the contextual ActionBar (CAB) is not open and I call isItemChecked() on a list item that I touch, it returns false as it should. But when the CAB IS open, items that I touch (that I haven't touched before) return true on calls to isItemChecked(). Then when I call delete on the array from getCheckedItemIds(), that array does not contain the items that were previously returning true for isItemChecked().

Has anyone seen this?

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.habit);
    habitListView = (ListView)findViewById(R.id.habitsListView);
    habitListView.setAdapter(mAdapter);
    habitListView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
    habitListView.setItemsCanFocus(false);
    habitListView.setOnItemLongClickListener(new MyOnItemLongClickListener());
    habitListView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if (habitListView.isItemChecked(position)) { // for debugging, returns false here
                                                         // when CAB isnt up.
                int h = 2;
            }
            // handle differently when CAB is on.
            if (mMode != null) {
                if (habitListView.isItemChecked(position)) { // returns true here when CAB is up
                                                             // but this is the first time I'm
                                                             // clicking the item
                    habitListView.setItemChecked(position, false);
                    // turn CAB off if this is the last to be unchecked
                    if (habitListView.getCheckedItemIds().length == 0) {
                        mMode.finish();
                    }
                } else {
                    habitListView.setItemChecked(position, true);
                }
            } else {
                // start detail/edit view activity
            }
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getSupportMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle item selection
    switch (item.getItemId()) {
    case R.id.menu_create:
        Habit test = new Habit("FLOSS", "GOOD", "", "");
        mDbHelper.createHabitEntry(test);
        mAdapter.changeCursor(mDbHelper.getAllEntries());
        break;
    }
    return false;
}

private class MyOnItemLongClickListener implements OnItemLongClickListener {
    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        habitListView.setItemChecked(position, true);
        mMode = startActionMode(new MyActionModeCallback());
        return true;
    }
}

private class MyActionModeCallback implements ActionMode.Callback {
    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        habitListView.setOnItemLongClickListener(new MyOnItemLongClickListener());
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mode.getMenuInflater().inflate(R.menu.main_long_click_context, menu);
        habitListView.setOnItemLongClickListener(null);
        return true;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_delete:
            long[] selected = habitListView.getCheckedItemIds();
            if (selected.length > 0) {
                for (long id : selected) {
                    mDbHelper.deleteEntry(id);
                }
            }
            mAdapter.changeCursor(mDbHelper.getAllEntries());
            mode.finish();
            break;
        }
        return true;
    }
};

Solution

  • So what has worked for me is to just use

       habitListView.setOnItemClickListener(new OnItemClickListener(){
    
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
    
                //handle differently when CAB is on.
                if (mMode != null){
    
                    view.setSelected(!view.isSelected());
    
                    updateCABtitle();
    
                    //turn CAB off if this is the last to be unchecked
                        if (habitListView.getCheckedItemIds().length == 0){
                            mMode.finish();
                        } 
    
                } else {
                    //start detail/edit view activity
                    Intent intent = new Intent(getApplicationContext(), HabitDetailActivity.class);
                    startActivity(intent);
    
                }
    
            }
    
        });
    

    and

        private class MyOnItemLongClickListener implements OnItemLongClickListener{
    
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view,
                        int position, long id) {
    
    
                habitListView.setItemChecked(position, true);
    
                mMode = startActionMode(new MyActionModeCallback());
                updateCABtitle();
    
                return true;
        }
    
    }
    

    I don't really understand why setItemChecked() is not working for onItemClick() but seems to be for onItemLongClick(). It looks as though there is a default click handler that gets called in AbsListView.PerformItemClick() that must do some toggling of checked/unchecked or something.