Android一步步帶你在RecyclerView上面實(shí)現(xiàn)"拖放"和"滑動(dòng)刪除"功能
先給大家展示下大概效果圖:
Android上面有許多的教程, 庫(kù)和示例, 在RecyclerView上面實(shí)現(xiàn)"拖放"和"滑動(dòng)刪除"功能. 盡管有更新, 更好的方法可用, 但是大多數(shù)人依然使用舊的View.OnDragListener和Roman Nurik的SwipeToDismiss方式. 除了經(jīng)常使用GestureDetector和onInterceptTouchEvent之外, 幾乎很少有人使用新的API, 要不然的話, 實(shí)現(xiàn)就復(fù)雜. 事實(shí)上真的有十分簡(jiǎn)單的方式在RecyclerView上面添加這兩個(gè)功能. 它只要求一個(gè)類, 而且這個(gè)類已經(jīng)是Android支持包的一部分.
ItemTouchHelper是一個(gè)強(qiáng)大的通用程序, 在RecyclerView上面添加"拖放"和"滑動(dòng)刪除"時(shí), 你所需要做的所有事情, 它都會(huì)負(fù)責(zé)處理. 它是RecyclerView.ItemDecoration的子類, 這意味著它可以輕易地添加到任何已經(jīng)存在的LayoutManager和Adapter上面! 它不會(huì)影響添加到item上的動(dòng)畫(huà), 并且支持類別嚴(yán)格的"拖", 以及"放"時(shí)的動(dòng)畫(huà), 還可以支持更多.
準(zhǔn)備:
首先, 我們所需要的是添加RecyclerView的依賴:
compile 'com.android.support:recyclerview-v7:25.3.0'
使用ItemTouchHelper和ItemTouchHelper.Callback:
為了使用ItemTouchHelper, 你將創(chuàng)建一個(gè)ItemTouchHelper.Callback, 這是一個(gè)接口, 允許你監(jiān)聽(tīng)"move"和"swipe"事件, 而且你可以通過(guò)Callback來(lái)控件已選中view的狀態(tài), 并且可以改變?cè)搗iew的默認(rèn)動(dòng)畫(huà). 如果只是想要一個(gè)基礎(chǔ)實(shí)現(xiàn), 你可以使用SimpleCallback這個(gè)幫助類, 但是為了學(xué)習(xí)Callback的工作原理, 我們將會(huì)自己實(shí)現(xiàn)一個(gè).
為了激活基本的"拖放"和"滑動(dòng)刪除", 我們必須覆蓋的主要方法是:
getMovementFlags(RecyclerView, ViewHolder) onMove(RecyclerView, ViewHolder, ViewHolder) onSwiped(ViewHolder, int)
我們也要使用這兩個(gè)方法:
isLongPressDragEnabled() isItemViewSwipeEnabled()
我們一個(gè)一個(gè)地看一下:
@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允許你輕易地決定事件的方向.你必須實(shí)現(xiàn)getMovementFlags(RecyclerView, RecyclerView.ViewHolder)方法來(lái)指明"拖"和"滑動(dòng)"所支持的方向, 并且使用ItemTouchHelper.makeMovementFlags(int, int)來(lái)構(gòu)建返回標(biāo)簽. 在此我們?cè)趦蓚€(gè)不同的方向激活"拖"和"滑動(dòng)".
@Override public boolean isLongPressDragEnabled() { return true; }
ItemTouchHelper能夠用來(lái)實(shí)現(xiàn)"沒(méi)有滑動(dòng)的拖動(dòng)"或者"沒(méi)有拖動(dòng)的滑動(dòng)", 所以你必須精確地指明想要支持的動(dòng)作. 如果你想要在RecyclerView的item上支持"長(zhǎng)按啟動(dòng)拖放"事件, 你就必須實(shí)現(xiàn)isLongPressDragEnabled()返回true. 此外, ItemTouchHelper.startDrag(RecyclerView.ViewHolder)可以從"操作"中啟動(dòng)"拖放", 這一點(diǎn)會(huì)在之后詳述.
@Override public boolean isItemViewSwipeEnabled() { return true; }
要想要view內(nèi)部的任意觸摸事件都可以啟動(dòng)"滑動(dòng)"動(dòng)作, 就簡(jiǎn)單地在isItemViewSwipeEnabled()返回true. 此外, ItemTouchHelper.startSwipe(RecyclerView.ViewHolder)能夠手動(dòng)地啟動(dòng)"滑動(dòng)"事件.
然后, onMove()和onSwiped()方法需要實(shí)現(xiàn), 來(lái)通知負(fù)責(zé)更新基礎(chǔ)數(shù)據(jù)的東西. 所以, 首先, 我們要?jiǎng)?chuàng)建一個(gè)接口, 以允許我們傳遞"拖放"和"滑動(dòng)刪除"事件的回調(diào).
public interface ItemTouchHelperAdapter { void onItemMove(int fromPosition, int toPosition); void onItemDismiss(int position); }
從當(dāng)前示例來(lái)講, 要實(shí)現(xiàn)這些的最簡(jiǎn)單的方式, 是將我們的RecyclerView.Adapter實(shí)現(xiàn)這個(gè)接口:
public class RecyclerListAdapter extends RecyclerView.Adapter<ItemViewHolder> implements ItemTouchHelperAdapter { // ... code from gist @Override public void onItemDismiss(int position) { mItems.remove(position); notifyItemRemoved(position); } @Override public boolean onItemMove(int fromPosition, int toPosition) { if (fromPosition < toPosition) { for (int i = fromPosition; i < toPosition; i++) { Collections.swap(mItems, i, i + 1); } } else { for (int i = fromPosition; i > toPosition; i--) { Collections.swap(mItems, i, i - 1); } } notifyItemMoved(fromPosition, toPosition); return true; }
調(diào)用notifyItemRemoved(int)和notifyItemMoved(int, int)是非常重要的, 由此, Adapter會(huì)更新數(shù)據(jù). 請(qǐng)注意, 這也很重要, 我們改變item的position是在每一次view被切換到新的index, 而不是在"放"事件之后.
現(xiàn)在我們回來(lái)構(gòu)建SimpleItemTouchHelperCallback, 因?yàn)槲覀円廊槐仨毟采wonMove()和onSwiped()方法. 首先, 為Adapter添加構(gòu)建器和變量:
private final ItemTouchHelperAdapter mAdapter; public SimpleItemTouchHelperCallback( ItemTouchHelperAdapter adapter) { mAdapter = adapter; }
然后覆蓋剩下的事件并通知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()); }
這個(gè)Callback應(yīng)該看起來(lái)像這樣:
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()); } }
當(dāng)Callback準(zhǔn)備好之后, 我們創(chuàng)建ItemTouchHelper并調(diào)用attachToRecyclerView(RecyclerView)方法:
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter); ItemTouchHelper touchHelper = new ItemTouchHelper(callback); touchHelper.attachToRecyclerView(recyclerView);
當(dāng)你運(yùn)行的時(shí)候, 結(jié)果應(yīng)該看起來(lái)像這樣:
總結(jié)
這是一個(gè)ItemTouchHelper極簡(jiǎn)單的實(shí)現(xiàn). 但是我們應(yīng)該清楚, 在RecyclerView上面實(shí)現(xiàn)基本的"拖放"和"滑動(dòng)刪除", 使用第三方和庫(kù)是完全沒(méi)有必要的.
以上所述是小編給大家介紹的Android一步步帶你在RecyclerView上面實(shí)現(xiàn)"拖放"和"滑動(dòng)刪除"功能,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Android開(kāi)發(fā)在RecyclerView上面實(shí)現(xiàn)"拖放"和"滑動(dòng)刪除"-2
- android RecyclerView側(cè)滑菜單,滑動(dòng)刪除,長(zhǎng)按拖拽,下拉刷新上拉加載
- android RecyclerView實(shí)現(xiàn)條目Item拖拽排序與滑動(dòng)刪除
- Android中RecyclerView實(shí)現(xiàn)滑動(dòng)刪除與拖拽功能
- Android 滑動(dòng)監(jiān)聽(tīng)RecyclerView線性流+左右劃刪除+上下移動(dòng)
- Android RecyclerView滑動(dòng)刪除和拖動(dòng)排序
- Android RecyclerView實(shí)現(xiàn)滑動(dòng)刪除
相關(guān)文章
activity全屏實(shí)現(xiàn)沉浸式效果,并且單獨(dú)觸摸不會(huì)彈出虛擬按鍵的方法
今天小編就為大家分享一篇activity全屏實(shí)現(xiàn)沉浸式效果,并且單獨(dú)觸摸不會(huì)彈出虛擬按鍵的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07解決Android Studio Log.v和Log.d不顯示的問(wèn)題
這篇文章主要介紹了解決Android Studio Log.v和Log.d不顯示的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08使用OkHttp包在Android中進(jìn)行HTTP頭處理的教程
HTTP頭部處理是HTTP網(wǎng)絡(luò)編程中的基本操作,安卓中使用OkHttp包(github.com/square/okhttp)進(jìn)行相關(guān)操作當(dāng)然也是得心應(yīng)手,這里我們就來(lái)看一下使用OkHttp包在Android中進(jìn)行HTTP頭處理的教程2016-07-07Android?PickerScrollView滑動(dòng)選擇控件使用方法詳解
這篇文章主要為大家詳細(xì)介紹了Android?PickerScrollView滑動(dòng)選擇控件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04Android仿淘寶頭條向上滾動(dòng)廣告條ViewFlipper
這篇文章主要為大家詳細(xì)介紹了Android仿淘寶頭條向上滾動(dòng)廣告條ViewFlipper,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05Android studio圓形進(jìn)度條 百分?jǐn)?shù)跟隨變化
這篇文章主要為大家詳細(xì)介紹了Android studio圓形進(jìn)度條,百分號(hào)跟隨變化,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10