Android - Swipe to delete RecyclerView
Simple Code for RecyclerView Swipe:
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT | ItemTouchHelper.DOWN | ItemTouchHelper.UP) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Toast.makeText(ListActivity.this, "on Move", Toast.LENGTH_SHORT).show();
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
Toast.makeText(ListActivity.this, "on Swiped ", Toast.LENGTH_SHORT).show();
//Remove swiped item from list and notify the RecyclerView
int position = viewHolder.getAdapterPosition();
arrayList.remove(position);
adapter.notifyDataSetChanged();
}
};
Then set callback for recyclerView with below statements:
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(rv);
Swipe to Dismiss for RecyclerView
As of v22.2.0, the Android support team has included an ItemTouchHelper
class that makes swipe-to-dismiss and drag-and-drop pretty simple. This may not be as full-featured as some of the libraries out there, but it comes directly from the Android team.
Update your build.gradle to import v22.2.+ of the RecyclerView library
compile 'com.android.support:recyclerview-v7:22.2.+'
Instantiate an ItemTouchHelper with an appropriate SimpleCallback
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
[...]
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
//Remove swiped item from list and notify the RecyclerView
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);** Note that the SimpleCallback takes in the directions that you want to enable drag-and-drop and the directions that you want to enable swiping.
Attach to your RecyclerView
itemTouchHelper.attachToRecyclerView(recyclerView);
Swiping to delete items of recyclerview doesnt work
Okay so I have finally found the problem.
I just had to initialize the ItemTouchHelper in the method where the RecyclerView
is built instead of in the onCreate method.
So this is what the code looks like:
private void buildRecyclerView() {
mRecyclerView = view.findViewById(R.id.recyclerview);
mLayoutManager = new LinearLayoutManager(getActivity());
mAdapter = new ExampleAdapter(mExampleList);
mRecyclerView.setLayoutManager(mLayoutManager);
new ItemTouchHelper(itemTochHelperCallback).attachToRecyclerView(mRecyclerView);
mRecyclerView.setAdapter(mAdapter);
}
ItemTouchHelper.SimpleCallback itemTochHelperCallback=new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
mExampleList.remove(viewHolder.getAdapterPosition());
mAdapter.notifyDataSetChanged();
}
};
Prevent swipe to delete recyclerview item
Your RecyclerView
has RecyclerView.Adapter
attached to it. The adapter determines what information that the RecyclerView
can see and display. So, if item number 10, out of a 100-item backing array (managed by you) is swiped, the adapter can report that the array now contains 99 items and not ever present the swiped item to the RecyclerView
. That way the item appears to be deleted but is maintained internally and still accessible programmatically. How you manage that internal state is up to you and dependent upon your implementation.
If, however you want to not remove the item from the screen but just change its appearance, I think that you would need to look at the method onItemDismiss
that actually removes the item and notifies the adapter of the data change.
public void onItemDismiss(int position) {
mItems.remove(position);
notifyItemRemoved(position);
}
It is here that you would make the change. The item would stay in the adapter. You would also need to flag that position as "swiped" in case the view holders are recycle so you can maintain the visual "swiped" state.
public void onItemDismiss(int position) {
// Change background color, etc.
}
Take a look at code that has a "swipe to delete" function with "undo" for some ideas. Here is an example with a dialog that is called before deletion actually occurs if "Cancel" is clicked. There are many other examples of "undo" available. What you are trying to do can be considered to be an immediate and implicit "undo" with a visual change to the background.
If you want to have the item move back into position after a swipe, the following should work:
public void onItemDismiss(int position) {
notifyItemChanged(position);
}
RecyclerView swiping to delete in Fragment?
I've fixed my issue by moving the Callback after I initialize my RecyclerView.
recyclerView = itemView.findViewById(R.id.recyclerView);
ItemTouchHelper.SimpleCallback ItemTouchHelperCallbackLeft = new RecyclerItemTouchHelper(0, ItemTouchHelper.LEFT, this);
new ItemTouchHelper(ItemTouchHelperCallbackLeft).attachToRecyclerView(recyclerView);
RecyclerView swipe to delete still shows drawable with uncomplete swipe
Modified the onChildDraw() of the custom ItemTouchHelper.SimpleCallback by settings the bounds of the icon to 0 when unswiped with mIcon.setBounds(0, 0, 0, 0);
public class ItemDragSwipeCallback extends ItemTouchHelper.SimpleCallback {
private Drawable mIcon;
private final ColorDrawable mBackground;
public interface OnTouchListener {
boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target);
void onSwiped(RecyclerView.ViewHolder viewHolder, int direction);
}
private OnTouchListener mOnTouchListener;
public ItemDragSwipeCallback(Context context, int backgroundColor, int drawable, int dragDirs, int swipeDirs, OnTouchListener onTouchListener) {
super(dragDirs, swipeDirs);
mOnTouchListener = onTouchListener;
mIcon = ContextCompat.getDrawable(context, drawable);
mBackground = new ColorDrawable(context.getResources().getColor(backgroundColor));
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return mOnTouchListener.onMove(recyclerView, viewHolder, target);
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
mOnTouchListener.onSwiped(viewHolder, direction);
}
@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
View itemView = viewHolder.itemView;
int backgroundCornerOffset = 25; //so mBackground is behind the rounded corners of itemView
int iconMargin = (itemView.getHeight() - mIcon.getIntrinsicHeight()) / 2;
int iconTop = itemView.getTop() + (itemView.getHeight() - mIcon.getIntrinsicHeight()) / 2;
int iconBottom = iconTop + mIcon.getIntrinsicHeight();
if (dX > 0) { // Swiping to the right
int iconLeft = itemView.getLeft() + iconMargin;
int iconRight = iconLeft + mIcon.getIntrinsicWidth();
mIcon.setBounds(iconLeft, iconTop, iconRight, iconBottom);
mBackground.setBounds(itemView.getLeft(), itemView.getTop(),
itemView.getLeft() + ((int) dX) + backgroundCornerOffset, itemView.getBottom());
} else if (dX < 0) { // Swiping to the left
int iconLeft = itemView.getRight() - iconMargin - mIcon.getIntrinsicWidth();
int iconRight = itemView.getRight() - iconMargin;
mIcon.setBounds(iconLeft, iconTop, iconRight, iconBottom);
mBackground.setBounds(itemView.getRight() + ((int) dX) - backgroundCornerOffset,
itemView.getTop(), itemView.getRight(), itemView.getBottom());
} else { // view is unSwiped
mIcon.setBounds(0, 0, 0, 0);
mBackground.setBounds(0, 0, 0, 0);
}
mBackground.draw(c);
mIcon.draw(c);
}
}
How to have swipe to delete and swipe to archive in two colours in Recyclerview Android
Use ItemTouchHelper to Implement the Gmail Like Feature
call the following function after setting the recyclerView
private fun initSwipe() {
val simpleItemTouchCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val position = viewHolder.adapterPosition
if (direction == ItemTouchHelper.LEFT) {
//Logic to do when swipe left
} else {
//Logic to do when swipe right
}
}
override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
val icon: Bitmap
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
//Drawing for Swife Right
val itemView = viewHolder.itemView
val height = itemView.bottom.toFloat() - itemView.top.toFloat()
val width = height / 3
if (dX > 0) {
p.color = Color.parseColor("#2F2FD3")
val background = RectF(itemView.left.toFloat(), itemView.top.toFloat(), dX, itemView.bottom.toFloat())
c.drawRect(background, p)
icon = BitmapFactory.decodeResource(resources, R.drawable.ic_archive)
val icon_dest = RectF(itemView.left.toFloat() + width, itemView.top.toFloat() + width, itemView.left.toFloat() + 2 * width, itemView.bottom.toFloat() - width)
c.drawBitmap(icon, null, icon_dest, p)
} else {
//Drawing for Swife Left
p.color = Color.parseColor("#D32F2F")
val background = RectF(itemView.right.toFloat() + dX, itemView.top.toFloat(), itemView.right.toFloat(), itemView.bottom.toFloat())
c.drawRect(background, p)
icon = BitmapFactory.decodeResource(resources, R.drawable.ic_delete)
val icon_dest = RectF(itemView.right.toFloat() - 2 * width, itemView.top.toFloat() + width, itemView.right.toFloat() - width, itemView.bottom.toFloat() - width)
c.drawBitmap(icon, null, icon_dest, p)
}
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
}
}
val itemTouchHelper = ItemTouchHelper(simpleItemTouchCallback)
itemTouchHelper.attachToRecyclerView(YOUR_RECYCLER_VIEW)
}
Where
Object p is an object of paint Paint p = new Paint()
Hope this may help you.
Related Topics
How to Implement Drag and Drop in Android 2.2
Hiding the Actionbar on Recyclerview/Listview Onscroll
How to Move the Layout Up When the Soft Keyboard Is Shown Android
How to Change the Size of a Switch Widget
App Not Run in Visual Studio Emulator for Android in Visual Studio 2015
Gradle Failed to Resolve Library in Android Studio
Which Architecture Patterns Are Used on Android
Viewpager in a Nestedscrollview
Permission Denial: Startforeground Requires Android.Permission.Foreground_Service
Refresh Fragment UI from Fragmentactivity
Disable Orange Outline Highlight on Focus
How to Animate a View with Translate Animation in Android
The Import Android.Support.V7 Cannot Be Resolved
How to Get Name of Wifi-Network Out of Android Using Android API
How to Change Textcolor in Alertdialog
How to Evenly Distribute Buttons Across the Width of a Linearlayout