Brief: Explanation with simple steps to how to re-order the list items by long press, drag and drop using recycler view in xamarin android.
In my previous post explained How to create image gallery control in xamarin form, How to encrypt sqlite database.
Description: If you are looking for a requirement of re arranging the list items based on some priority then you are in the right place and here you can go through the example. Lets get in to the steps,
Step1: Create the new xamarin native project and add the below required packages.
On installation of above packages it will install all the required child packages also.
Step2: Create UI
Add new layout file one for recycler view and another one to dispay custom row item.
ReOrderLayout.axml
In my example considered displaying quiz question with answer requiring to set the item in correct order.
CustomListItemReorder.axml
Step3: Add Interfaces
Need to add two interface to deifne touch and drag
1. IOnStartDragListener.cs
OnStartDrag : Called when a view is requesting a start of a drag and accepts viewHolder of the recycler view to drag.
2. ITemTouchHelperAdapter.cs
OnItemMove : Called when an item has been dragged far enough to trigger a move. This is called every time an item is shifted, and not at the end of a "drop" event.
OnItemDismiss:Called when an item has been dismissed by a swipe
Step4: Add ItemTouchHelperCallback Class
Create new class SimpleItemTouchHelperCallback by inheriting from ItemTouchHelper.Callback
Here overriden below three methods provided by the ItemTouchHelper.Callback base class
1.GetMovementFlags : To update the touch movement state
2.OnMove : To Notify the adapter of the moved position
3.OnSwiped : To Notify the adapter of the dismissal
SimpleItemTouchHelperCallback.cs
Step5: Create Adapter and view holder Class
Here ReOrderAdapters implemented ITemTouchHelperAdapter for the above mentioned functionality and IOnLongClickListener
to listen to the long click event.
SimpleItemTouchHelperCallback.cs
In my previous post explained How to create image gallery control in xamarin form, How to encrypt sqlite database.
Description: If you are looking for a requirement of re arranging the list items based on some priority then you are in the right place and here you can go through the example. Lets get in to the steps,
Step1: Create the new xamarin native project and add the below required packages.
1 2 | Xamarin.Android.Support.v4 Xamarin.Android.Support.v7 |
Step2: Create UI
Add new layout file one for recycler view and another one to dispay custom row item.
ReOrderLayout.axml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:orientation="vertical" | |
android:background="@android:color/white"> | |
<LinearLayout | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:orientation="vertical" | |
android:layout_marginBottom="5dp" | |
android:layout_above="@+id/mLLButtonContainer"> | |
<TextView | |
android:id="@+id/reorderTitle" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:paddingLeft="10dp" | |
android:paddingRight="10dp" | |
android:text="1.Set the below items in correct order" | |
android:gravity="center_vertical" | |
android:textAppearance="?android:textAppearanceMedium" | |
android:textColor="#ff000000" | |
android:background="@android:color/white" | |
android:maxLines="1" | |
android:ellipsize="end" | |
android:paddingTop="5dp" | |
android:paddingBottom="5dp" /> | |
<View | |
android:layout_width="match_parent" | |
android:layout_height="1dp" | |
android:layout_marginTop="1dp" | |
android:background="@android:color/darker_gray"/> | |
<android.support.v7.widget.RecyclerView | |
android:id="@+id/ResourceReorderRecyclerView" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:layout_marginTop="20dp" /> | |
</LinearLayout> | |
<TextView | |
android:id="@+id/mDone" | |
android:layout_width="wrap_content" | |
android:layout_height="40dp" | |
android:layout_centerInParent="true" | |
android:textColor="@android:color/black" | |
android:text="Done" | |
android:maxLines="1" | |
android:ellipsize="end" | |
android:layout_gravity="center_horizontal" | |
android:paddingRight="40dp" | |
android:paddingLeft="40dp" | |
android:background="@android:color/darker_gray" | |
android:paddingTop="1dp" | |
android:paddingBottom="5dp" | |
android:textSize="16dp" | |
android:layout_marginTop="5dp" | |
android:gravity="center_vertical" | |
android:layout_marginBottom="5dp" /> | |
</LinearLayout> |
In my example considered displaying quiz question with answer requiring to set the item in correct order.
CustomListItemReorder.axml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:id="@+id/ReorderView" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:orientation="vertical" | |
android:background="@android:color/transparent"> | |
<RelativeLayout | |
android:layout_width="match_parent" | |
android:layout_height="60dp" | |
android:paddingTop="5dp" | |
android:paddingBottom="5dp" | |
android:background="@android:color/transparent" | |
android:gravity="center_horizontal"> | |
<TextView | |
android:id="@+id/mTVResourceName" | |
android:textAppearance="?android:attr/textAppearanceSmall" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_alignParentLeft="true" | |
android:layout_centerInParent="true" | |
android:layout_toLeftOf="@+id/mTvReorderIcon" | |
android:text="sample" | |
android:textColor="@android:color/black" | |
android:maxLines="1" | |
android:ellipsize="end" | |
android:paddingLeft="5dp" | |
android:paddingRight="5dp" | |
android:layout_marginLeft="8dp" | |
android:textSize="15dp" | |
android:layout_centerVertical="true" /> | |
<ImageView | |
android:id="@+id/mTvReorderIcon" | |
android:layout_width="90dp" | |
android:layout_height="45dp" | |
android:paddingRight="10dp" | |
android:src="@drawable/icns_reorder2" | |
android:layout_alignParentRight="true" | |
android:clickable="false" | |
android:layout_centerVertical="true" /> | |
</RelativeLayout> | |
<View | |
android:layout_width="match_parent" | |
android:layout_height="1dp" | |
android:layout_marginTop="3dp" | |
android:background="@android:color/darker_gray" /> | |
</LinearLayout> |
Need to add two interface to deifne touch and drag
1. IOnStartDragListener.cs
OnStartDrag : Called when a view is requesting a start of a drag and accepts viewHolder of the recycler view to drag.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Android.Support.V7.Widget; | |
namespace NativeCodeLog.Droid | |
{ | |
public interface IOnStartDragListener | |
{ | |
void OnStartDrag(RecyclerView.ViewHolder viewHolder); | |
} | |
} |
OnItemMove : Called when an item has been dragged far enough to trigger a move. This is called every time an item is shifted, and not at the end of a "drop" event.
OnItemDismiss:Called when an item has been dismissed by a swipe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace NativeCodeLog.Droid | |
{ | |
public interface ITemTouchHelperAdapter | |
{ | |
/** | |
* @param fromPosition The start position of the moved item. | |
* @param toPosition Then resolved position of the moved item. | |
* @return True if the item was moved to the new adapter position. | |
*/ | |
bool OnItemMove(int fromPosition, int toPosition); | |
/** | |
* @param position The position of the item dismissed. | |
* @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder) | |
* @see RecyclerView.ViewHolder#getAdapterPosition() | |
*/ | |
void OnItemDismiss(int position); | |
} | |
} |
Here overriden below three methods provided by the ItemTouchHelper.Callback base class
1.GetMovementFlags : To update the touch movement state
2.OnMove : To Notify the adapter of the moved position
3.OnSwiped : To Notify the adapter of the dismissal
SimpleItemTouchHelperCallback.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Android.Support.V7.Widget.Helper; | |
using Android.Support.V7.Widget; | |
namespace NativeCodeLog.Droid | |
{ | |
public class SimpleItemTouchHelperCallback : ItemTouchHelper.Callback | |
{ | |
private readonly ITemTouchHelperAdapter _mAdapter; | |
public SimpleItemTouchHelperCallback(ITemTouchHelperAdapter adapter) | |
{ | |
_mAdapter = adapter; | |
} | |
public override int GetMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) | |
{ | |
const int dragFlags = ItemTouchHelper.Up | ItemTouchHelper.Down; | |
const int swipeFlags = ItemTouchHelper.ActionStateIdle; | |
return MakeMovementFlags(dragFlags, swipeFlags); | |
} | |
public override bool OnMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) | |
{ | |
if (viewHolder.ItemViewType != target.ItemViewType) | |
{ | |
return false; | |
} | |
// Notify the adapter of the move | |
_mAdapter.OnItemMove(viewHolder.AdapterPosition, target.AdapterPosition); | |
return true; | |
} | |
public override void OnSwiped(RecyclerView.ViewHolder viewHolder, int direction) | |
{ | |
// Notify the adapter of the dismissal | |
_mAdapter.OnItemDismiss(viewHolder.AdapterPosition); | |
} | |
} | |
public class ReOrderViewHolder : RecyclerView.ViewHolder | |
{ | |
public LinearLayout ReorderView; | |
public ImageView ReorderIcon; | |
public TextView ResourceName; | |
public ReOrderViewHolder(View view) : base(view) | |
{ | |
ResourceName = view.FindViewById<TextView>(Resource.Id.mTVResourceName); | |
ReorderView = view.FindViewById<LinearLayout>(Resource.Id.ReorderView); | |
ReorderIcon = view.FindViewById<ImageView>(Resource.Id.mTvReorderIcon); | |
} | |
} | |
} |
Step5: Create Adapter and view holder Class
Here ReOrderAdapters implemented ITemTouchHelperAdapter for the above mentioned functionality and IOnLongClickListener
to listen to the long click event.
SimpleItemTouchHelperCallback.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Android.Support.V7.Widget.Helper; | |
using Android.Support.V7.Widget; | |
namespace NativeCodeLog.Droid | |
{ | |
public class SimpleItemTouchHelperCallback : ItemTouchHelper.Callback | |
{ | |
private readonly ITemTouchHelperAdapter _mAdapter; | |
public SimpleItemTouchHelperCallback(ITemTouchHelperAdapter adapter) | |
{ | |
_mAdapter = adapter; | |
} | |
public override int GetMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) | |
{ | |
const int dragFlags = ItemTouchHelper.Up | ItemTouchHelper.Down; | |
const int swipeFlags = ItemTouchHelper.ActionStateIdle; | |
return MakeMovementFlags(dragFlags, swipeFlags); | |
} | |
public override bool OnMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) | |
{ | |
if (viewHolder.ItemViewType != target.ItemViewType) | |
{ | |
return false; | |
} | |
// Notify the adapter of the move | |
_mAdapter.OnItemMove(viewHolder.AdapterPosition, target.AdapterPosition); | |
return true; | |
} | |
public override void OnSwiped(RecyclerView.ViewHolder viewHolder, int direction) | |
{ | |
// Notify the adapter of the dismissal | |
_mAdapter.OnItemDismiss(viewHolder.AdapterPosition); | |
} | |
} | |
public class ReOrderViewHolder : RecyclerView.ViewHolder | |
{ | |
public LinearLayout ReorderView; | |
public ImageView ReorderIcon; | |
public TextView ResourceName; | |
public ReOrderViewHolder(View view) : base(view) | |
{ | |
ResourceName = view.FindViewById<TextView>(Resource.Id.mTVResourceName); | |
ReorderView = view.FindViewById<LinearLayout>(Resource.Id.ReorderView); | |
ReorderIcon = view.FindViewById<ImageView>(Resource.Id.mTvReorderIcon); | |
} | |
} | |
} |
Step6: Add Activity Class
Created the activity ReOrderActivity and implemeted interface IOnStartDragListener.
ReOrderActivity.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.ObjectModel; | |
using Android.App; | |
using Android.OS; | |
using Android.Support.V7.Widget; | |
using Android.Support.V7.Widget.Helper; | |
namespace NativeCodeLog.Droid | |
{ | |
[Activity(Label = "ReOrderList")] | |
public class ReOrderActivity : Activity, IOnStartDragListener | |
{ | |
private ItemTouchHelper _mItemTouchHelper; | |
public static ObservableCollection<string> ResourceList; | |
private RecyclerView _resourceReorderRecyclerView; | |
protected override void OnCreate(Bundle savedInstanceState) | |
{ | |
base.OnCreate(savedInstanceState); | |
SetContentView(Resource.Layout.ReOrderLayout); | |
GetCollection(); | |
var resourceAdapter = new ReOrderAdapters(ResourceList, this); | |
// Initialize the recycler view. | |
_resourceReorderRecyclerView = FindViewById<RecyclerView>(Resource.Id.ResourceReorderRecyclerView); | |
_resourceReorderRecyclerView.SetLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.Vertical, false)); | |
_resourceReorderRecyclerView.SetAdapter(resourceAdapter); | |
_resourceReorderRecyclerView.HasFixedSize = true; | |
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(resourceAdapter); | |
_mItemTouchHelper = new ItemTouchHelper(callback); | |
_mItemTouchHelper.AttachToRecyclerView(_resourceReorderRecyclerView); | |
} | |
public void OnStartDrag(RecyclerView.ViewHolder viewHolder) | |
{ | |
_mItemTouchHelper.StartDrag(viewHolder); | |
} | |
//Added sample data record here | |
public void GetCollection() | |
{ | |
ResourceList = new ObservableCollection<string>(); | |
ResourceList.Add("OnPause()"); | |
ResourceList.Add("OnStart()"); | |
ResourceList.Add("OnCreate()"); | |
} | |
} | |
} |
Git link: https://github.com/suchithm/NativeCodeLog
Screen recording:
This is all about the implementation of reorder list in xamarin android using recycler view. Keep visiting for more exciting stuffs and follow us on FB Page.
NotifyDataSetChanged() alone wont help in showing index of each item. you need to update custom layout text view with position and position based on OnItemMove()
ReplyDeleteHello, thank you for this tutorial. I'm hoping you can help. I now have firebase realtime database set up with my app but now the drag and drop feature on my items no longer work.
ReplyDeleteI can drag the items but they just hover over all the other items and when I start dragging an item the other items don't move to fill the space.
Do you have any idea how I can fix this?
Thanks
Doesn't matter which database you used here. Just check OnMove method in SimpleItemTouchHelperCallback class something missed here.
DeleteAdding reordering items is currently one of my most challenging tasks on my current app, so hopefully your tutorial will help me. However, because my app uses Xamarin.Forms, one thing that I hope to do at some point is convert your code into a Custom Renderer. If you have any suggestions comments or suggestions for doing this, it would be appreciated (along with the already much appreciated tutorial!). Thanks!
ReplyDeleteJust use sharpnado's HorizontalListView
DeleteI cannot find ReOrderAdapter.cs?? Where to fond it?
ReplyDeleteYou can refer it from here : https://github.com/suchithm/NativeCodeLog/blob/master/Droid/ReOrder/ReOrderAdapter.cs
Delete