nispok/snackbar

Associate data with Snackbar

Closed this issue · 1 comments

tyczj commented

I am showing a snackbar when I delete remove something from my RecyclerView so the user can choose to "Undo" the deletion like in Gmail but what I am struggling with is how to associate data with a snackbar.

For example the user clicks on the undo I will just call notifyDatasetChanged on the adapter to bring back all the data again which is fine but the problem is when I want to delete that entry for good. Since onDismiss gets called no matter what how do I know weather its being dismissed from an action click or the snackbar time out/dismissal

For my project, I handled this by creating a new ArrayList and adding the elements from the main ArrayList that are to be deleted. I keep their locations in a SparseBooleanArray. So, delete them and notifyItemRemoved on each so they animate out. Then, in the Snackbar onActionClicked, I add them back to the main ArrayList then notifyItemInserted on each, which animates them back into place. Avoid notifyDatasetChanged whenever possible; it'll kill your animations.

Here's my code:

case R.id.action_delete:
                //Save the characters and positions temporarily in case the user wants to undo the delete
                final ArrayList<GameCharacter> storedCharacters = new ArrayList<>();
                final SparseBooleanArray storedPositions = selectedItems.clone();  //Creating a copy of the positions was necessary because other parts of my code could clear selectedItems before the Snackbar finished
                for(int i = 0; i<storedPositions.size(); i++){
                    storedCharacters.add(gameCharacterList.get(storedPositions.keyAt(i)));
                }

                //Delete the characters
                for (int i = selectedItems.size() - 1; i >= 0; i--) {
                    gameCharacterList.remove(selectedItems.keyAt(i));
                    recyclerViewAdapter.notifyItemRemoved(selectedItems.keyAt(i));
                }
                selectedItems.clear();
                resetDefaultMenu(); //I'm using a gmail-like functionality that changes the toolbar and statusbar to grey while items have been selected. This restores the normal colors and resets the menu action items

                //Allow the user to undo delete
                SnackbarManager.show(
                        Snackbar.with(getApplicationContext())
                                .text(getString(R.string.deleted_count, storedPositions.size())) // text to display
                                .actionLabel(getString(R.string.undo))
                                .actionColor(getResources().getColor(R.color.accent))
                                .actionListener(new ActionClickListener() {
                                    @Override
                                    public void onActionClicked(Snackbar snackbar) {
                                        //User clicked UNDO, so add the stored characters back in their original positions
                                        for (int i = 0; i < storedPositions.size(); i++) {
                                            gameCharacterList.add(storedPositions.keyAt(i), storedCharacters.get(i));
                                            recyclerViewAdapter.notifyItemInserted(storedPositions.keyAt(i));
                                        }
                                    }
                                }), this); 
                break;

Hope this helps.