TonicArtos / StickyGridHeaders

This project has been superseded by SuperSLiM, a layout manager for RecyclerView. I strongly recommend using SuperSLiM and not StickyGridHeaders.
http://tonicartos.com
Apache License 2.0
1.47k stars 442 forks source link

AbsListView.CHOICE_MODE_MULTIPLE is not working #42

Closed mcohnen closed 6 years ago

mcohnen commented 11 years ago

Hi,

If I enable that value, the cells are not being checked properly. Using a regular GridView works with this. I'm trying to find what of the methods you override is breaking that behavior, but just in case this is a limitation we can not go around.

TonicArtos commented 11 years ago

I haven't tried supporting multichoice yet. I'll have time to look at it soon.

mcohnen commented 11 years ago

Great, thank you!

vovan888 commented 10 years ago

Any updates on this ? getCheckedItemIds() always returns empty list

hendrawd commented 8 years ago

How do you guys resolve this issue? I need to resolve this issue too. I first use https://github.com/TonicArtos/SuperSLiM and then use this one instead because super slim can't detect end of scroll correctly. Now i need to implement contextual action bar for selecting multiple items on grid view. If you guys have workaround let me know, thank you very much.

hendrawd commented 8 years ago

If anyone want to solve the same problem i have a solution here. The idea is that you must handle the contextual action bar and checked ids by yourself

set these in your fragment or activity

   gridView.setChoiceMode(GridView.CHOICE_MODE_NONE);
   gridView.setOnItemLongClickListener(this);
   gridView.setOnItemClickListener(this);

where gridView is your StickyGridHeadersGridView and you should implement AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener or make a new one that can be used on that setOnItemLongClickListener and OnItemClickListener

Create this class on your activity or fragment

 private class ActionModeCallback implements ActionMode.Callback {

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // inflate contextual menu
        mode.getMenuInflater().inflate(R.menu.do_something, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.do_something:
                SparseBooleanArray selected = yourAdapter.getSelectedIds();
                StringBuilder sb = new StringBuilder();
                for (int i = (selected.size() - 1); i >= 0; i--) {
                    if (selected.valueAt(i)) {
                        sb.append(selected.keyAt(i));
                        if (i > 0) {
                            sb.append(", ");
                        }
                    }
                }
                //this is a custom toast that i made, you can replace it with toast or whatever
                Utils.showCustomToast(NewMainActivity.this, sb.toString());
                mode.finish();
                return true;
            default:
                return false;
        }
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        yourAdapter.removeSelection();
        mActionMode = null;
    }
}

then make these methods

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    if (mActionMode == null) {
        //perform your standard operation when item on click
    } else
        onListItemSelect(position);
}

@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
    onListItemSelect(position);
    return true;
}

private void onListItemSelect(int position) {
    yourAdapter.toggleSelection(position);
    boolean hasCheckedItems = yourAdapter.getSelectedCount() > 0;

    if (hasCheckedItems && mActionMode == null)
        // there are some selected items, start the actionMode
        mActionMode = startActionMode(new ActionModeCallback());
    else if (!hasCheckedItems && mActionMode != null)
        // there no selected items, finish the actionMode
        mActionMode.finish();

    if (mActionMode != null)
        mActionMode.setTitle(String.valueOf(yourAdapter
                .getSelectedCount()) + " selected");
}

Add this variable to your activity or fragment as global variable

 private ActionMode mActionMode;

Then in your adapter, add this variable

  private SparseBooleanArray mSelectedItemsIds = new SparseBooleanArray();

And add these methods

public void selectView(int position, boolean value) {
    if (value)
        mSelectedItemsIds.put(position, true);
    else
        mSelectedItemsIds.delete(position);
    notifyDataSetChanged();
}

public void toggleSelection(int position) {
    selectView(position, !mSelectedItemsIds.get(position));
}

public void removeSelection() {
    mSelectedItemsIds = new SparseBooleanArray();
    notifyDataSetChanged();
}

public int getSelectedCount() {
    return mSelectedItemsIds.size();
}

public SparseBooleanArray getSelectedIds() {
    return mSelectedItemsIds;
}

I hope this solution will help you guys, sorry if too long, contact me if you have any problem or didn't understand