
هناك العديد من البرامج التعليمية والمكتبات وأمثلة السحب والإفلات والتمرير السريع للرفض في Android باستخدام RecyclerView. لا يزال معظمهم يستخدمون View.OnDragListener وطريقة SwipeToDismiss التي طورها Roman Nurik. على الرغم من توفر طرق جديدة وأكثر فعالية. يستخدم عدد قليل جدًا أحدث واجهات برمجة التطبيقات ، غالبًا ما يعتمدون على GestureDetectors
و onInterceptTouchEvent
أو onInterceptTouchEvent
أخرى أكثر تعقيدًا. في الواقع ، هناك طريقة بسيطة جدًا لإضافة هذه الوظائف إلى RecyclerView
. يتطلب هذا فئة واحدة فقط ، والتي تعد أيضًا جزءًا من مكتبة دعم Android.
ItemTouchHelper
يعد ItemTouchHelper أداة مساعدة فعالة تهتم بكل ما عليك القيام به لإضافة وظائف السحب والإفلات والتمرير السريع RecyclerView
إلى RecyclerView
. هذه الأداة هي فئة فرعية من RecyclerView.ItemDecoration ، مما يسهل إضافتها إلى أي LayoutManager
ومحول موجود تقريبًا. كما أنها تعمل مع الرسوم المتحركة للعناصر وتوفر القدرة على سحب وإفلات عناصر من نوع واحد إلى مكان آخر في القائمة وأكثر من ذلك بكثير. في هذه المقالة ، ItemTouchHelper
تنفيذًا بسيطًا لـ ItemTouchHelper
. لاحقًا ، كجزء من سلسلة المقالات هذه ، سنقوم بتوسيع النطاق والنظر في الخيارات الأخرى.
ملاحظة تريد أن ترى النتيجة على الفور؟ تحقق من Github: Android-ItemTouchHelper-Demo . الالتزام الأول يتعلق بهذه المقالة. يمكن تنزيل ملف .apk
التجريبي هنا .

التخصيص
نحتاج أولاً إلى تكوين RecyclerView
. إذا لم تكن قد قمت بذلك بالفعل ، أضف تبعية RecyclerView
إلى ملف build.gradle
.
compile 'com.android.support:recyclerview-v7:22.2.0'
سيعمل ItemTouchHelper
تقريبًا مع أي RecyclerView.Adapter
و LayoutManager
، ولكن هذه المقالة تستند إلى أمثلة تستخدم هذه الملفات .
استخدام ItemTouchHelper و ItemTouchHelper.Callback
لاستخدام ItemTouchHelper
، تحتاج إلى إنشاء ItemTouchHelper.Callback . هذه واجهة تسمح لك بتتبع إجراءات الحركة ( eng. Move) والتمرير السريع ( eng. Swipe). بالإضافة إلى ذلك ، يمكنك هنا التحكم في حالة مكون view
المحدد وتجاوز الرسم المتحرك الافتراضي. هناك فئة مساعدة يمكنك استخدامها إذا كنت ترغب في استخدام التطبيق الأساسي ، SimpleCallback . ولكن من أجل فهم كيفية عمل ذلك عمليًا ، سنفعل كل شيء بمفردنا.
الوظائف الرئيسية للواجهة التي يجب علينا إعادة تعريفها لتشمل الوظائف الأساسية للسحب والإفلات والتمرير السريع للرفض :
getMovementFlags(RecyclerView, ViewHolder) onMove(RecyclerView, ViewHolder, ViewHolder) onSwiped(ViewHolder, int)
سنستخدم أيضًا عدة طرق مساعدة:
isLongPressDragEnabled() isItemViewSwipeEnabled()
دعونا نعتبرها واحدة تلو الأخرى.
@Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; return makeMovementFlags(dragFlags, swipeFlags); }
ItemTouchHelper
تسهيل تحديد اتجاه الحدث. تحتاج إلى تجاوز طريقة getMovementFlags()
للإشارة إلى الاتجاهات التي سيتم دعمها في السحب والإفلات. لإنشاء علامات الإرجاع ، استخدم أسلوب المساعد ItemTouchHelper.makeMovementFlags(int, int)
. في هذا المثال ، نسمح بالسحب والإفلات في كلا الاتجاهين.
@Override public boolean isLongPressDragEnabled() { return true; }
يمكن استخدام ItemTouchHelper
فقط للسحب والإفلات بدون وظيفة السحب (أو العكس) ، لذا يجب عليك تحديد الميزات التي يجب دعمها بالضبط. يجب أن ترجع طريقة isLongPressDragEnabled()
true
لدعم السحب والإفلات بعد نقرة طويلة على عنصر RecyclerView
. بدلاً من ذلك ، يمكنك استدعاء أسلوب ItemTouchHelper.startDrag(RecyclerView.ViewHolder)
لبدء السحب يدويًا. سننظر في هذا الخيار لاحقًا.
@Override public boolean isItemViewSwipeEnabled() { return true; }
لتمكين الخفق بعد لمس أي مكان داخل مكون view
، ما isItemViewSwipeEnabled()
سوى إرجاع true
من طريقة isItemViewSwipeEnabled()
. بدلاً من ذلك ، يمكنك استدعاء أسلوب ItemTouchHelper.startSwipe(RecyclerView.ViewHolder)
لبدء التمرير يدويًا.
الطريقتان onMove()
، onMove()
و onSwiped()
، onSwiped()
بتحديثات البيانات. لذا ، أولاً سننشئ واجهة تسمح بتمرير هذه الأحداث عبر سلسلة الاتصال.
ItemTouchHelperAdapter.java
public interface ItemTouchHelperAdapter { void onItemMove(int fromPosition, int toPosition); void onItemDismiss(int position); }
أسهل طريقة للقيام بذلك هي جعل RecyclerListAdapter يطبق المستمع.
public class RecyclerListAdapter extends RecyclerView.Adapter<ItemViewHolder> implements ItemTouchHelperAdapter {
من المهم جدًا استدعاء notifyItemRemoved()
و notifyItemMoved()
حتى يرى المحول التغييرات. وتجدر الإشارة أيضًا إلى أننا نغير موضع العنصر في كل مرة يتم فيها تحويل مكون view
إلى فهرس جديد ، وليس في نهاية الحركة (حدث "الإفلات") .
يمكننا الآن العودة إلى إنشاء SimpleItemTouchHelperCallback
، لأننا ما زلنا بحاجة إلى تجاوز onMove()
و onSwiped()
. قم أولاً بإضافة المُنشئ والحقل للمحول:
private final ItemTouchHelperAdapter mAdapter; public SimpleItemTouchHelperCallback( ItemTouchHelperAdapter adapter) { mAdapter = adapter; }
ثم أعد تحديد الأحداث المتبقية وأبلغ المحول بهذا:
@Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { mAdapter.onItemDismiss(viewHolder.getAdapterPosition()); }
نتيجة لذلك ، يجب أن تبدو فئة Callback
مثل هذا:
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { private final ItemTouchHelperAdapter mAdapter; public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) { mAdapter = adapter; } @Override public boolean isLongPressDragEnabled() { return true; } @Override public boolean isItemViewSwipeEnabled() { return true; } @Override public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; return makeMovementFlags(dragFlags, swipeFlags); } @Override public boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target) { mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onSwiped(ViewHolder viewHolder, int direction) { mAdapter.onItemDismiss(viewHolder.getAdapterPosition()); } }
عندما يكون ItemTouchHelper
جاهزًا ، يمكننا إنشاء ItemTouchHelper
واستدعاء طريقة attachToRecyclerView(RecyclerView)
(على سبيل المثال ، في MainFragment.java ):
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter); ItemTouchHelper touchHelper = new ItemTouchHelper(callback); touchHelper.attachToRecyclerView(recyclerView);
بعد البدء ، يجب أن تحصل على شيء مثل ما يلي:

الخلاصة
هذا هو أبسط تطبيق ItemTouchHelper
. ومع ذلك ، قد تلاحظ أنه لا يتعين عليك استخدام مكتبة جهة خارجية لتنفيذ إجراءات السحب والإفلات القياسية والتمرير السريع RecyclerView
في RecyclerView
. في الجزء التالي ، سنولي المزيد من الاهتمام لمظهر العناصر في وقت السحب والإفلات.
كود المصدر
لقد أنشأت مشروعًا على GitHub لشرح ما يتم تناوله في هذه السلسلة من المقالات: Android-ItemTouchHelper-Demo . يتعلق الالتزام الأول بشكل أساسي بهذا الجزء وقليلاً بالجزء الثاني .
→ اسحب واسحب في برنامج RecyclerView. الجزء 2: سحب وإسقاط وحدات التحكم والشبكات والرسوم المتحركة المخصصة