Reputation: 117
Hello everyone my name is Taniguchi:
I have a recyclerview and i wish to swipe to Delete in xamarin android but i only find articles in java
does anyone knows how to do it in C# ?
The java article teaching how to swipe to delete.
https://medium.com/@zackcosborn/step-by-step-recyclerview-swipe-to-delete-and-undo-7bbae1fce27e
my recylerview adapter:
public class RecyclerAdapter : RecyclerView.Adapter, View.IOnClickListener, View.IOnLongClickListener
{
private View view;
private Boolean isSelected = false;
public Boolean IsSelected()
{
return isSelected;
}
public void setSelected(Boolean selected)
{
isSelected = selected;
}
public static RecyclerView.Adapter mAdapter;
public static bool isActionMode = true;
private int viewType;
private ViewGroup parent;
public static bool unselect = false;
private Activity mActivity;
private MyActionMode mActionMode;
private RecyclerView.ViewHolder holder;
private List<time_entry> mTime_Entries;
private Context context;
private View p;
private ActionMode mode;
public static bool count = false;
public static int CountAuxiliar = 0;
private MyActionMode myActionMode;
public event EventHandler<int> ItemClick;
public RecyclerAdapter(List<time_entry> time_entries, Context context)
{
mTime_Entries = time_entries;
this.context = context;
}
public RecyclerAdapter(List<time_entry> time_entries, Activity activity)
{
mTime_Entries = time_entries;
mActivity = activity;
}
public RecyclerAdapter(List<time_entry> time_entries, MyActionMode myActionMode)
{
mTime_Entries = time_entries;
this.myActionMode = myActionMode;
}
public class MyView : RecyclerView.ViewHolder
{
public View mMainView {get; set;}
public TextView mName {get; set;}
public TextView mSubject {get; set;}
public TextView mMessage {get; set;}
public MyView(View view) : base(view)
{
mMainView = view;
}
}
public override int ItemCount
{
get { return mTime_Entries.Count; }
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
LayoutInflater inflater = LayoutInflater.From(parent.Context);
View row = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.row, parent, false);
RecyclerViewHolder vh = new RecyclerViewHolder(row);
return vh;
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
RecyclerViewHolder myHolder = holder as RecyclerViewHolder;
myHolder.cbx.Visibility = mTime_Entries[position].IsSelected() ? ViewStates.Visible : ViewStates.Gone;
myHolder.cbx.Checked = mTime_Entries[position].IsSelected();
myHolder.mProject_Task.Text = mTime_Entries[position].projectTask;
myHolder.mDate.Text = mTime_Entries[position].date;
myHolder.mDescription.Text = mTime_Entries[position].description;
myHolder.ItemView.SetBackgroundColor(mTime_Entries[position].IsSelected() ? Color.LightBlue : Color.Transparent);
myHolder.ItemView.Tag = position;
myHolder.ItemView.SetOnClickListener(this);
myHolder.ItemView.SetOnLongClickListener(this);
}
void View.IOnClickListener.OnClick(View v)
{
if (CountAuxiliar > 0)
{
int position = (int)v.Tag;
mTime_Entries[position].setSelected(!mTime_Entries[position].IsSelected());
v.SetBackgroundColor(mTime_Entries[position].IsSelected() ? Color.LightBlue : Color.Transparent);
v.FindViewById(Resource.Id.checkBox1).Visibility = mTime_Entries[position].IsSelected() ? ViewStates.Visible : ViewStates.Invisible;
if (mTime_Entries[position].IsSelected())
{
CountAuxiliar++;
}
else
{
CountAuxiliar--;
}
//mode.Title = CountAuxiliar.ToString() + " " + "Selecionados";
MainActivity.title.Text = CountAuxiliar.ToString() + " " + "Selecionados";
Toast.MakeText(v.Context, "Click : " + CountAuxiliar + "---" + position, ToastLength.Short).Show();
}
if (CountAuxiliar < 1 && count == true)
{
count = false;
MainActivity.toolbar2.Visibility = ViewStates.Gone;
MainActivity.bottomnavigationview1.Visibility = ViewStates.Gone;
MainActivity.floatinactionbutton1.Visibility = ViewStates.Visible;
}
}
public void removeSelection()
{
if (mTime_Entries != null)
{
foreach (time_entry email in mTime_Entries)
{
email.setSelected(false);
}
}
NotifyDataSetChanged();
CountAuxiliar = 0;
count = false;
MainActivity.bottomnavigationview1.Visibility = ViewStates.Gone;
MainActivity.floatinactionbutton1.Visibility = ViewStates.Visible;
}
public void checkall()
{
if (mTime_Entries != null)
{
foreach (time_entry email in mTime_Entries)
{
email.setSelected(true);
}
}
NotifyDataSetChanged();
MainActivity.bottomnavigationview1.Visibility = ViewStates.Visible;
}
public bool OnLongClick(View v)
{
if (CountAuxiliar < 1)
{
CountAuxiliar = 1;
count = true;
int position = (int)v.Tag;
mTime_Entries[position].setSelected(!mTime_Entries[position].IsSelected());
v.SetBackgroundColor(mTime_Entries[position].IsSelected() ? Color.LightBlue : Color.Transparent);
MainActivity.bottomnavigationview1.Visibility = ViewStates.Visible;
MainActivity.floatinactionbutton1.Visibility = ViewStates.Gone;
v.FindViewById(Resource.Id.checkBox1).Visibility = mTime_Entries[position].IsSelected() ? ViewStates.Visible : ViewStates.Invisible;
MainActivity.title.Text = CountAuxiliar.ToString() + " " + "Selecionado";
MainActivity.toolbar2.Visibility = ViewStates.Visible;
count = true;
Toast.MakeText(v.Context, "Long Click : " + mTime_Entries[position].IsSelected() + "---" + position, ToastLength.Short).Show();
}
return true;
}
}
Upvotes: 4
Views: 1276
Reputation: 12723
You can custom a SwipeToDeleteCallback
inherited from ItemTouchHelper.SimpleCallback to realize it , here is an article for reference .
SwipeToDeleteCallback class:
public class SwipeToDeleteCallback : ItemTouchHelper.SimpleCallback
{
private Context context;
private PhotoAlbumAdapter madapter;
private Android.Graphics.Drawables.Drawable deleteIcon;
private int intrinsicWidth;
private int intrinsicHeight;
private Android.Graphics.Drawables.ColorDrawable background;
private Color backgroundColor;
private Paint clearPaint;
public SwipeToDeleteCallback(int dragDirs, int swipeDirs, Context context) : base(dragDirs, swipeDirs )
{
this.context = context;
deleteIcon = ContextCompat.GetDrawable(context, Resource.Drawable.alter_delete);
intrinsicWidth = deleteIcon.IntrinsicWidth;
intrinsicHeight = deleteIcon.IntrinsicHeight;
background = new Android.Graphics.Drawables.ColorDrawable();
backgroundColor = Color.ParseColor("#f44336");
clearPaint = new Paint();
clearPaint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.Clear));
}
public SwipeToDeleteCallback(int dragDirs, int swipeDirs, Context context, PhotoAlbumAdapter mRecyclerView) : this(dragDirs, swipeDirs, context)
{
this.context = context;
this.madapter = mRecyclerView;
deleteIcon = ContextCompat.GetDrawable(context, Resource.Drawable.delete);
intrinsicWidth = deleteIcon.IntrinsicWidth;
intrinsicHeight = deleteIcon.IntrinsicHeight;
background = new Android.Graphics.Drawables.ColorDrawable();
backgroundColor = Color.ParseColor("#f44336");
clearPaint = new Paint();
clearPaint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.Clear));
}
public override int GetMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
{
if(viewHolder.AdapterPosition == 10)
{
return 0;
}
return base.GetMovementFlags(recyclerView, viewHolder);
}
public override void OnChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, bool isCurrentlyActive)
{
base.OnChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
public override bool OnMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)
{
//throw new NotImplementedException();
return false;
}
public override void OnChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, bool isCurrentlyActive)
{
var itemView = viewHolder.ItemView;
var itemHeight = itemView.Bottom - itemView.Top;
var isCanceled = dX == 0f && !isCurrentlyActive;
if (isCanceled)
{
clearCanvas(c, itemView.Right + dX, (float)itemView.Top, (float)itemView.Right, (float)itemView.Bottom);
base.OnChildDrawOver(c, recyclerView
, viewHolder, dX, dY, actionState, isCurrentlyActive);
return;
}
background.Color = backgroundColor;
background.SetBounds(itemView.Right + (int)dX, itemView.Top, itemView.Right, itemView.Bottom);
background.Draw(c);
var deleteIconTop = itemView.Top + (itemHeight - intrinsicHeight) / 2;
var deleteIconMargin = (itemHeight - intrinsicHeight) / 2;
var deleteIconLeft = itemView.Right - deleteIconMargin - intrinsicWidth;
var deleteIconRight = itemView.Right - deleteIconMargin;
var deleteIconBottom = deleteIconTop + intrinsicHeight;
deleteIcon.SetBounds(deleteIconLeft, deleteIconTop, deleteIconRight, deleteIconBottom);
deleteIcon.Draw(c);
base.OnChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
private void clearCanvas(Canvas c, float v, float top, float right, float bottom)
{
c.DrawRect(v, top, right, bottom, clearPaint);
}
public override void OnSwiped(RecyclerView.ViewHolder viewHolder, int direction)
{
//Invoke Removing Item method from adapter
this.madapter.RemoveItem(viewHolder.AdapterPosition);
}
public override void ClearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
{
base.ClearView(recyclerView, viewHolder);
}
}
Then in Activity can use it as follow:
var swipeHandler = new SwipeToDeleteCallback(0, ItemTouchHelper.Left, this, mAdapter);
var itemTouchHelper = new ItemTouchHelper(swipeHandler);
itemTouchHelper.AttachToRecyclerView(mRecyclerView);
Not forgetting to add Remove method in Adapter :
public void RemoveItem (int position)
{
ArrayList al = new ArrayList(mPhotoAlbum.mPhotos);
al.RemoveAt(position);
mPhotoAlbum.mPhotos = (Photo[])al.ToArray(typeof(Photo));
NotifyDataSetChanged();
NotifyItemChanged(position);
}
Maybe from code not understanding totally , I refer to this sample to realize it . And the modified sample will share here . The effect is as follow:
===================================Update====================================
From shared project , there are two places need to modify.
First is RemoveItem
method in RecyclerAdapter class.Because my project use Object[]
to set source for RecycleView , need to write code to convert to be a ArrayList
.However ,the source (mTime_Entries
) of your project is also a List[] , so not need to convert it. Modify as follow in your project:
public void RemoveItem(int position)
{
mTime_Entries.RemoveAt(position);
NotifyDataSetChanged();
NotifyItemChanged(position);
}
Second is OnSwiped
method in SwipeToDeleteCallback class.Before this , you also need to modify the constructor of SwipeToDeleteCallback
. The Adapter is not correct here.
private RecyclerAdapter mdapter;
public SwipeToDeleteCallback(int dragDirs, int swipeDirs, Context context, PhotoAlbumAdapter mRecyclerView) : this(dragDirs, swipeDirs, context)
{
this.context = context;
this.madapter = mRecyclerView;
deleteIcon = ContextCompat.GetDrawable(context, Resource.Drawable.delete);
intrinsicWidth = deleteIcon.IntrinsicWidth;
intrinsicHeight = deleteIcon.IntrinsicHeight;
background = new Android.Graphics.Drawables.ColorDrawable();
backgroundColor = Color.ParseColor("#f44336");
clearPaint = new Paint();
clearPaint.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.Clear));
}
You should keep them(Adapter) be the same between MainActity and here.
Then OnSwiped
can be written with one line code as follow:
public override void OnSwiped(RecyclerView.ViewHolder viewHolder, int direction)
{
//Invoke Removing Item method from
this.mdapter.RemoveItem(viewHolder.AdapterPosition);
}
Upvotes: 3