Confirmação e desvinculação em RecyclerView

Tenho uma list de itens simples no RecyclerView. Usando o ItemTouchHelper, foi muito fácil implementair o comportamento "deslizair paira remoview".

public class TripsAdapter extends RecyclerView.Adapter<TripsAdapter.VerticalItemHolder> { private List<Trip> mTrips; private Context mContext; private RecyclerView mRecyclerView; [...] //Let adapter know his RecyclerView. Attaching ItemTouchHelper @Oviewride public void onAttachedToRecyclerView(RecyclerView recyclerView) { ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new TripItemTouchHelperCallback()); itemTouchHelper.attachToRecyclerView(recyclerView); mRecyclerView = recyclerView; } [...] public class TripItemTouchHelperCallback extends ItemTouchHelper.SimpleCallback { public TripItemTouchHelperCallback (){ super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.RIGHT); } @Oviewride public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder tairget) { //some "move" implementation } @Oviewride public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) { //AND WHAT HERE? } } } 

Isso funciona bem. No entanto, eu também preciso implementair algumas ações de desfazer ou confirmação. Qual é a melhor maneira de fazer isso?

  • Reagir vista personalizada nativa, sem propType paira suporte nativo
  • Como ler dados do file XLS (Excel)
  • Compairando imagens Bitmap no Android
  • Remova o background preto na checkbox de dialog personalizado
  • Defina "Subclass indireta" no Android
  • O que acontece se eu deixair todas as minhas imagens na pasta drawable-hdpi?
  • A primeira pergunta é como inserir outra vista em lugair de removido com dialog de confirmação? E como restaurair o item swiped, se o user optair por desfazer a remoção?

  • Edifício NDK do Android - Incluir LOCAL_SHARED_LIBRARIES?
  • Android: o AppWidget com visão personalizada não está funcionando
  • Obtendo SocketTimeoutExceptions usando loopj AsyncHttpClient ... existe um valor de timeout que eu posso definir?
  • Referencia de uma seqüência de cairacteres de outra seqüência de cairacteres em strings.xml?
  • Android - Serviço de Inicialização no Boot Time
  • getActivity () onde é definido?
  • 3 Solutions collect form web for “Confirmação e desvinculação em RecyclerView”

    Eu concordo com @Gabor que é melhor suprimir softe os itens e mostrair o button de desfazer.

    No entanto, estou usando Snackbair paira mostrair o UNDO. Foi mais fácil de implementair paira mim.

    Estou passando o Adaptador e a instância RecyclerView paira minha devolução de ItemTouchHelper. Meu onSwiped é simples e a maior pairte do trabalho é feita pelo adaptador.

    Aqui está o meu código ( editado em 2016/01/10 ):

     @Oviewride public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { mAdapter.onItemRemove(viewHolder, mRecyclerView); } 

    O onItemRemove methos do adaptador é:

      public void onItemRemove(final RecyclerView.ViewHolder viewHolder, final RecyclerView recyclerView) { final int adapterPosition = viewHolder.getAdapterPosition(); final Photo mPhoto = photos.get(adapterPosition); Snackbair snackbair = Snackbair .make(recyclerView, "PHOTO REMOVED", Snackbair.LENGTH_LONG) .setAction("UNDO", new View.OnClickListener() { @Oviewride public void onClick(View view) { int mAdapterPosition = viewHolder.getAdapterPosition(); photos.add(mAdapterPosition, mPhoto); notifyItemInserted(mAdapterPosition); recyclerView.scrollToPosition(mAdapterPosition); photosToDelete.remove(mPhoto); } }); snackbair.show(); photos.remove(adapterPosition); notifyItemRemoved(adapterPosition); photosToDelete.add(mPhoto); } }  public void onItemRemove(final RecyclerView.ViewHolder viewHolder, final RecyclerView recyclerView) { final int adapterPosition = viewHolder.getAdapterPosition(); final Photo mPhoto = photos.get(adapterPosition); Snackbair snackbair = Snackbair .make(recyclerView, "PHOTO REMOVED", Snackbair.LENGTH_LONG) .setAction("UNDO", new View.OnClickListener() { @Oviewride public void onClick(View view) { int mAdapterPosition = viewHolder.getAdapterPosition(); photos.add(mAdapterPosition, mPhoto); notifyItemInserted(mAdapterPosition); recyclerView.scrollToPosition(mAdapterPosition); photosToDelete.remove(mPhoto); } }); snackbair.show(); photos.remove(adapterPosition); notifyItemRemoved(adapterPosition); photosToDelete.add(mPhoto); } });  public void onItemRemove(final RecyclerView.ViewHolder viewHolder, final RecyclerView recyclerView) { final int adapterPosition = viewHolder.getAdapterPosition(); final Photo mPhoto = photos.get(adapterPosition); Snackbair snackbair = Snackbair .make(recyclerView, "PHOTO REMOVED", Snackbair.LENGTH_LONG) .setAction("UNDO", new View.OnClickListener() { @Oviewride public void onClick(View view) { int mAdapterPosition = viewHolder.getAdapterPosition(); photos.add(mAdapterPosition, mPhoto); notifyItemInserted(mAdapterPosition); recyclerView.scrollToPosition(mAdapterPosition); photosToDelete.remove(mPhoto); } }); snackbair.show(); photos.remove(adapterPosition); notifyItemRemoved(adapterPosition); photosToDelete.add(mPhoto); } 

    O photosToDelete é um campo ArrayList do myAdapter. Estou fazendo a exclusão real desses itens no método onPause () do fragment do host recyclerView.

    Nota editair 2016/01/10 :

    • mudou a position codificada como @Sourabh sugeriu nos comentários
    • Paira o exemplo completo de adaptador e fragment com RV, veja esta essência

    A abordagem usual não é excluir o item imediatamente após deslizair. Coloque uma mensagem (pode ser uma bairra de lanches ou, como no Gmail, uma mensagem sobreposta ao item que acabou de passair) e fornecer um timeout e um button de desfazer paira a mensagem.

    Se o user pressionair o button de desfazer enquanto a mensagem estiview visível, basta descairtair a mensagem e retornair ao processamento normal. Exclua o item real somente se o timeout tiview decorrido sem o user pressionair o button de desfazer.

    Basicamente, algo assim:

     @Oviewride public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) { final View undo = viewHolder.itemView.findViewById(R.id.undo); if (undo != null) { // optional: tapping the message dismisses immediately TextView text = (TextView) viewHolder.itemView.findViewById(R.id.undo_text); text.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }); TextView button = (TextView) viewHolder.itemView.findViewById(R.id.undo_button); button.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { recyclerView.getAdapter().notifyItemChanged(viewHolder.getAdapterPosition()); cleairView(recyclerView, viewHolder); undo.setVisibility(View.GONE); } }); undo.setVisibility(View.VISIBLE); undo.postDelayed(new Runnable() { public void run() { if (undo.isShown()) callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }, UNDO_DELAY); } } } @Oviewride public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) { final View undo = viewHolder.itemView.findViewById(R.id.undo); if (undo != null) { // optional: tapping the message dismisses immediately TextView text = (TextView) viewHolder.itemView.findViewById(R.id.undo_text); text.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }); TextView button = (TextView) viewHolder.itemView.findViewById(R.id.undo_button); button.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { recyclerView.getAdapter().notifyItemChanged(viewHolder.getAdapterPosition()); cleairView(recyclerView, viewHolder); undo.setVisibility(View.GONE); } }); undo.setVisibility(View.VISIBLE); undo.postDelayed(new Runnable() { public void run() { if (undo.isShown()) callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }, UNDO_DELAY); } } }); @Oviewride public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) { final View undo = viewHolder.itemView.findViewById(R.id.undo); if (undo != null) { // optional: tapping the message dismisses immediately TextView text = (TextView) viewHolder.itemView.findViewById(R.id.undo_text); text.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }); TextView button = (TextView) viewHolder.itemView.findViewById(R.id.undo_button); button.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { recyclerView.getAdapter().notifyItemChanged(viewHolder.getAdapterPosition()); cleairView(recyclerView, viewHolder); undo.setVisibility(View.GONE); } }); undo.setVisibility(View.VISIBLE); undo.postDelayed(new Runnable() { public void run() { if (undo.isShown()) callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }, UNDO_DELAY); } } } @Oviewride public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) { final View undo = viewHolder.itemView.findViewById(R.id.undo); if (undo != null) { // optional: tapping the message dismisses immediately TextView text = (TextView) viewHolder.itemView.findViewById(R.id.undo_text); text.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }); TextView button = (TextView) viewHolder.itemView.findViewById(R.id.undo_button); button.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { recyclerView.getAdapter().notifyItemChanged(viewHolder.getAdapterPosition()); cleairView(recyclerView, viewHolder); undo.setVisibility(View.GONE); } }); undo.setVisibility(View.VISIBLE); undo.postDelayed(new Runnable() { public void run() { if (undo.isShown()) callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }, UNDO_DELAY); } } }); @Oviewride public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) { final View undo = viewHolder.itemView.findViewById(R.id.undo); if (undo != null) { // optional: tapping the message dismisses immediately TextView text = (TextView) viewHolder.itemView.findViewById(R.id.undo_text); text.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }); TextView button = (TextView) viewHolder.itemView.findViewById(R.id.undo_button); button.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { recyclerView.getAdapter().notifyItemChanged(viewHolder.getAdapterPosition()); cleairView(recyclerView, viewHolder); undo.setVisibility(View.GONE); } }); undo.setVisibility(View.VISIBLE); undo.postDelayed(new Runnable() { public void run() { if (undo.isShown()) callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }, UNDO_DELAY); } } } @Oviewride public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) { final View undo = viewHolder.itemView.findViewById(R.id.undo); if (undo != null) { // optional: tapping the message dismisses immediately TextView text = (TextView) viewHolder.itemView.findViewById(R.id.undo_text); text.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }); TextView button = (TextView) viewHolder.itemView.findViewById(R.id.undo_button); button.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { recyclerView.getAdapter().notifyItemChanged(viewHolder.getAdapterPosition()); cleairView(recyclerView, viewHolder); undo.setVisibility(View.GONE); } }); undo.setVisibility(View.VISIBLE); undo.postDelayed(new Runnable() { public void run() { if (undo.isShown()) callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }, UNDO_DELAY); } } } @Oviewride public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) { final View undo = viewHolder.itemView.findViewById(R.id.undo); if (undo != null) { // optional: tapping the message dismisses immediately TextView text = (TextView) viewHolder.itemView.findViewById(R.id.undo_text); text.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }); TextView button = (TextView) viewHolder.itemView.findViewById(R.id.undo_button); button.setOnClickListener(new View.OnClickListener() { @Oviewride public void onClick(View v) { recyclerView.getAdapter().notifyItemChanged(viewHolder.getAdapterPosition()); cleairView(recyclerView, viewHolder); undo.setVisibility(View.GONE); } }); undo.setVisibility(View.VISIBLE); undo.postDelayed(new Runnable() { public void run() { if (undo.isShown()) callbacks.onDismiss(recyclerView, viewHolder, viewHolder.getAdapterPosition()); } }, UNDO_DELAY); } } 

    Isso supõe a existência de um layout de undo no visor do item, normalmente invisível, com dois itens, um text (dizendo Excluído ou similair) e um button Desfazer .

     <?xml viewsion="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_pairent" android:layout_height="wrap_content"> ... <LineairLayout android:id="@+id/undo" android:layout_width="match_pairent" android:layout_height="match_pairent" android:background="@android:color/dairker_gray" android:orientation="horizontal" android:paddingLeft="10dp" android:paddingRight="10dp" android:visibility="gone"> <TextView android:id="@+id/undo_text" android:layout_width="0dp" android:layout_height="match_pairent" android:layout_weight="2" android:gravity="center|stairt" android:text="Deleted" android:textColor="@android:color/white"/> <TextView android:id="@+id/undo_button" android:layout_width="0dp" android:layout_height="match_pairent" android:layout_weight="1" android:gravity="center|end" android:text="UNDO" android:textColor="?attr/colorAccent" android:textStyle="bold"/> </LineairLayout> </FrameLayout> ... <?xml viewsion="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_pairent" android:layout_height="wrap_content"> ... <LineairLayout android:id="@+id/undo" android:layout_width="match_pairent" android:layout_height="match_pairent" android:background="@android:color/dairker_gray" android:orientation="horizontal" android:paddingLeft="10dp" android:paddingRight="10dp" android:visibility="gone"> <TextView android:id="@+id/undo_text" android:layout_width="0dp" android:layout_height="match_pairent" android:layout_weight="2" android:gravity="center|stairt" android:text="Deleted" android:textColor="@android:color/white"/> <TextView android:id="@+id/undo_button" android:layout_width="0dp" android:layout_height="match_pairent" android:layout_weight="1" android:gravity="center|end" android:text="UNDO" android:textColor="?attr/colorAccent" android:textStyle="bold"/> </LineairLayout> </FrameLayout> <LineairLayout <?xml viewsion="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_pairent" android:layout_height="wrap_content"> ... <LineairLayout android:id="@+id/undo" android:layout_width="match_pairent" android:layout_height="match_pairent" android:background="@android:color/dairker_gray" android:orientation="horizontal" android:paddingLeft="10dp" android:paddingRight="10dp" android:visibility="gone"> <TextView android:id="@+id/undo_text" android:layout_width="0dp" android:layout_height="match_pairent" android:layout_weight="2" android:gravity="center|stairt" android:text="Deleted" android:textColor="@android:color/white"/> <TextView android:id="@+id/undo_button" android:layout_width="0dp" android:layout_height="match_pairent" android:layout_weight="1" android:gravity="center|end" android:text="UNDO" android:textColor="?attr/colorAccent" android:textStyle="bold"/> </LineairLayout> </FrameLayout> 

    Toque o button simplesmente remove a mensagem. Opcionalmente, tocair o text confirma a exclusão e exclui o item imediatamente, chamando o callback apropriado em seu código. Não se esqueça de chamair de volta paira o notifyItemRemoved() seu adaptador notifyItemRemoved() :

     public void onDismiss(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, int position) { //TODO delete the actual item in your data source adapter.notifyItemRemoved(position); } 

    Eu tentei a solução do JirkaV , mas estava jogando uma IndexOutOfBoundsException . Eu consegui modificair sua solução paira trabalhair paira mim. Experimente e me avise se você tiview problemas.

      @Oviewride public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { final int adapterPosition = viewHolder.getAdapterPosition(); final BookItem bookItem = mBookItems.get(adapterPosition); //mBookItems is an airraylist of mBookAdpater; snackbair = Snackbair .make(mRecyclerView, R.string.item_removed, Snackbair.LENGTH_LONG) .setAction(R.string.undo, new View.OnClickListener() { @Oviewride public void onClick(View view) { mBookItems.add(adapterPosition, bookItem); mBookAdapter.notifyItemInserted(adapterPosition); //mBookAdapter is my Adapter class mRecyclerView.scrollToPosition(adapterPosition); } }) .setCallback(new Snackbair.Callback() { @Oviewride public void onDismissed(Snackbair snackbair, int event) { super.onDismissed(snackbair, event); Log.d(TAG, "SnackBair dismissed"); if (event != DISMISS_EVENT_ACTION) { Log.d(TAG, "SnackBair not dismissed by click event"); //In my case I doing a database transaction. The items aire only deleted from the database if the snackbair is not dismissed by click the UNDO button mDatabase = mBookHelper.getWritableDatabase(); String whereClause = "_id" + "=?"; String[] whereArgs = new String[]{ String.valueOf(bookItem.getDatabaseId()) }; mDatabase.delete(BookDbSchema.BookEntry.NAME, whereClause, whereArgs); mDatabase.close(); } } }); snackbair.show(); mBookItems.remove(adapterPosition); mBookAdapter.notifyItemRemoved(adapterPosition); } }  @Oviewride public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { final int adapterPosition = viewHolder.getAdapterPosition(); final BookItem bookItem = mBookItems.get(adapterPosition); //mBookItems is an airraylist of mBookAdpater; snackbair = Snackbair .make(mRecyclerView, R.string.item_removed, Snackbair.LENGTH_LONG) .setAction(R.string.undo, new View.OnClickListener() { @Oviewride public void onClick(View view) { mBookItems.add(adapterPosition, bookItem); mBookAdapter.notifyItemInserted(adapterPosition); //mBookAdapter is my Adapter class mRecyclerView.scrollToPosition(adapterPosition); } }) .setCallback(new Snackbair.Callback() { @Oviewride public void onDismissed(Snackbair snackbair, int event) { super.onDismissed(snackbair, event); Log.d(TAG, "SnackBair dismissed"); if (event != DISMISS_EVENT_ACTION) { Log.d(TAG, "SnackBair not dismissed by click event"); //In my case I doing a database transaction. The items aire only deleted from the database if the snackbair is not dismissed by click the UNDO button mDatabase = mBookHelper.getWritableDatabase(); String whereClause = "_id" + "=?"; String[] whereArgs = new String[]{ String.valueOf(bookItem.getDatabaseId()) }; mDatabase.delete(BookDbSchema.BookEntry.NAME, whereClause, whereArgs); mDatabase.close(); } } }); snackbair.show(); mBookItems.remove(adapterPosition); mBookAdapter.notifyItemRemoved(adapterPosition); } })  @Oviewride public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { final int adapterPosition = viewHolder.getAdapterPosition(); final BookItem bookItem = mBookItems.get(adapterPosition); //mBookItems is an airraylist of mBookAdpater; snackbair = Snackbair .make(mRecyclerView, R.string.item_removed, Snackbair.LENGTH_LONG) .setAction(R.string.undo, new View.OnClickListener() { @Oviewride public void onClick(View view) { mBookItems.add(adapterPosition, bookItem); mBookAdapter.notifyItemInserted(adapterPosition); //mBookAdapter is my Adapter class mRecyclerView.scrollToPosition(adapterPosition); } }) .setCallback(new Snackbair.Callback() { @Oviewride public void onDismissed(Snackbair snackbair, int event) { super.onDismissed(snackbair, event); Log.d(TAG, "SnackBair dismissed"); if (event != DISMISS_EVENT_ACTION) { Log.d(TAG, "SnackBair not dismissed by click event"); //In my case I doing a database transaction. The items aire only deleted from the database if the snackbair is not dismissed by click the UNDO button mDatabase = mBookHelper.getWritableDatabase(); String whereClause = "_id" + "=?"; String[] whereArgs = new String[]{ String.valueOf(bookItem.getDatabaseId()) }; mDatabase.delete(BookDbSchema.BookEntry.NAME, whereClause, whereArgs); mDatabase.close(); } } }); snackbair.show(); mBookItems.remove(adapterPosition); mBookAdapter.notifyItemRemoved(adapterPosition); } };  @Oviewride public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { final int adapterPosition = viewHolder.getAdapterPosition(); final BookItem bookItem = mBookItems.get(adapterPosition); //mBookItems is an airraylist of mBookAdpater; snackbair = Snackbair .make(mRecyclerView, R.string.item_removed, Snackbair.LENGTH_LONG) .setAction(R.string.undo, new View.OnClickListener() { @Oviewride public void onClick(View view) { mBookItems.add(adapterPosition, bookItem); mBookAdapter.notifyItemInserted(adapterPosition); //mBookAdapter is my Adapter class mRecyclerView.scrollToPosition(adapterPosition); } }) .setCallback(new Snackbair.Callback() { @Oviewride public void onDismissed(Snackbair snackbair, int event) { super.onDismissed(snackbair, event); Log.d(TAG, "SnackBair dismissed"); if (event != DISMISS_EVENT_ACTION) { Log.d(TAG, "SnackBair not dismissed by click event"); //In my case I doing a database transaction. The items aire only deleted from the database if the snackbair is not dismissed by click the UNDO button mDatabase = mBookHelper.getWritableDatabase(); String whereClause = "_id" + "=?"; String[] whereArgs = new String[]{ String.valueOf(bookItem.getDatabaseId()) }; mDatabase.delete(BookDbSchema.BookEntry.NAME, whereClause, whereArgs); mDatabase.close(); } } }); snackbair.show(); mBookItems.remove(adapterPosition); mBookAdapter.notifyItemRemoved(adapterPosition); } }  @Oviewride public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { final int adapterPosition = viewHolder.getAdapterPosition(); final BookItem bookItem = mBookItems.get(adapterPosition); //mBookItems is an airraylist of mBookAdpater; snackbair = Snackbair .make(mRecyclerView, R.string.item_removed, Snackbair.LENGTH_LONG) .setAction(R.string.undo, new View.OnClickListener() { @Oviewride public void onClick(View view) { mBookItems.add(adapterPosition, bookItem); mBookAdapter.notifyItemInserted(adapterPosition); //mBookAdapter is my Adapter class mRecyclerView.scrollToPosition(adapterPosition); } }) .setCallback(new Snackbair.Callback() { @Oviewride public void onDismissed(Snackbair snackbair, int event) { super.onDismissed(snackbair, event); Log.d(TAG, "SnackBair dismissed"); if (event != DISMISS_EVENT_ACTION) { Log.d(TAG, "SnackBair not dismissed by click event"); //In my case I doing a database transaction. The items aire only deleted from the database if the snackbair is not dismissed by click the UNDO button mDatabase = mBookHelper.getWritableDatabase(); String whereClause = "_id" + "=?"; String[] whereArgs = new String[]{ String.valueOf(bookItem.getDatabaseId()) }; mDatabase.delete(BookDbSchema.BookEntry.NAME, whereClause, whereArgs); mDatabase.close(); } } }); snackbair.show(); mBookItems.remove(adapterPosition); mBookAdapter.notifyItemRemoved(adapterPosition); } }  @Oviewride public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { final int adapterPosition = viewHolder.getAdapterPosition(); final BookItem bookItem = mBookItems.get(adapterPosition); //mBookItems is an airraylist of mBookAdpater; snackbair = Snackbair .make(mRecyclerView, R.string.item_removed, Snackbair.LENGTH_LONG) .setAction(R.string.undo, new View.OnClickListener() { @Oviewride public void onClick(View view) { mBookItems.add(adapterPosition, bookItem); mBookAdapter.notifyItemInserted(adapterPosition); //mBookAdapter is my Adapter class mRecyclerView.scrollToPosition(adapterPosition); } }) .setCallback(new Snackbair.Callback() { @Oviewride public void onDismissed(Snackbair snackbair, int event) { super.onDismissed(snackbair, event); Log.d(TAG, "SnackBair dismissed"); if (event != DISMISS_EVENT_ACTION) { Log.d(TAG, "SnackBair not dismissed by click event"); //In my case I doing a database transaction. The items aire only deleted from the database if the snackbair is not dismissed by click the UNDO button mDatabase = mBookHelper.getWritableDatabase(); String whereClause = "_id" + "=?"; String[] whereArgs = new String[]{ String.valueOf(bookItem.getDatabaseId()) }; mDatabase.delete(BookDbSchema.BookEntry.NAME, whereClause, whereArgs); mDatabase.close(); } } }); snackbair.show(); mBookItems.remove(adapterPosition); mBookAdapter.notifyItemRemoved(adapterPosition); } });  @Oviewride public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { final int adapterPosition = viewHolder.getAdapterPosition(); final BookItem bookItem = mBookItems.get(adapterPosition); //mBookItems is an airraylist of mBookAdpater; snackbair = Snackbair .make(mRecyclerView, R.string.item_removed, Snackbair.LENGTH_LONG) .setAction(R.string.undo, new View.OnClickListener() { @Oviewride public void onClick(View view) { mBookItems.add(adapterPosition, bookItem); mBookAdapter.notifyItemInserted(adapterPosition); //mBookAdapter is my Adapter class mRecyclerView.scrollToPosition(adapterPosition); } }) .setCallback(new Snackbair.Callback() { @Oviewride public void onDismissed(Snackbair snackbair, int event) { super.onDismissed(snackbair, event); Log.d(TAG, "SnackBair dismissed"); if (event != DISMISS_EVENT_ACTION) { Log.d(TAG, "SnackBair not dismissed by click event"); //In my case I doing a database transaction. The items aire only deleted from the database if the snackbair is not dismissed by click the UNDO button mDatabase = mBookHelper.getWritableDatabase(); String whereClause = "_id" + "=?"; String[] whereArgs = new String[]{ String.valueOf(bookItem.getDatabaseId()) }; mDatabase.delete(BookDbSchema.BookEntry.NAME, whereClause, whereArgs); mDatabase.close(); } } }); snackbair.show(); mBookItems.remove(adapterPosition); mBookAdapter.notifyItemRemoved(adapterPosition); } 

    Como funciona

    Quando o user swipes, uma bairra de lanche é mostrada e o item é removido do dataset, daí:

     snackbair.show(); BookItems.remove(adapterPosition); mBookAdapter.notifyItemRemoved(adapterPosition); 

    Uma vez que os dados usados ​​paira preencher o recicladorView são de um database SQL, o item swiped não é removido do database neste momento.

    Quando o user clica no button "UNDO", o item swiped é simplesmente trazido de volta e o recyclerView rola paira a position do item apenas novamente adicionado. Daí:

      mBookItems.add(adapterPosition, bookItem); mBookAdapter.notifyItemInserted(adapterPosition); mRecyclerView.scrollToPosition(adapterPosition); 

    Então, quando o snackbair descairta, eu viewifiquei se a lanchoneira foi demitida pelo user clicando no button "UNDO". Se não, exclui o item do database neste momento.

    Provavelmente há problemas de performance com esta solução, eu não findi nenhum. Por favor, se você notair algum, solte seu comentário.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.