RecyclerView 梳理:點選&長按事件、分割線、拖曳排序、滑動刪除
本文作者
作者:OCNYang
連結:http://www.jianshu.com/p/70788a7a5547
本文由作者投稿釋出。
這次主要是把 RecyclerView 比較常用的基本的點,在這裡集中整理一下。從這篇文章主要梳理以下幾點:
-
優雅的實現:item 點選事件 & item 長點選事件
-
RecyclerView 新增 divider 的標準姿勢
-
RecyclerView 實現 item 的拖曳排序和滑動刪除
-
拖曳排序時,限制首個 item 固定的實現
先看一下最終的效果圖:
--swipe and drag--
--drag--
自從 RecyclerView 釋出以來,由於其高度的可互動性被廣泛使用。相信大家肯定對它的使用方法已經非常熟練了,今天主要是為大家總結一下較正常用法更加優雅的方式。
如果你想再回顧一下 RecyclerView 的基本使用方法,推薦鴻洋的這篇文章:
《Android RecyclerView 使用完全解析 體驗藝術般的控制元件》
http://blog.csdn.net/lmj623565791/article/details/45059587
1
使用方式
RecyclerView 的 api 雖然沒有提供 onItemClickListener 但是提供了 addOnItemTouchListener() 方法,既然可以新增觸控監聽,那麼我們完全可以獲取觸控手勢來識別點選事件,然後通過觸控座標來判斷點選的是哪一個item。
其中 OnRecyclerItemClickListener 是自定義的一個觸控監聽器,程式碼如下:
GestureDetectorCompat 中傳入了一個 ItemTouchHelperGestureListener,程式碼如下:
原理分析
上面的程式碼很簡單沒什麼複雜的地方,就是通過一個手勢探測器 GestureDetectorCompat 來探測螢幕事件,然後通過手勢監聽器 SimpleOnGestureListener 來識別手勢事件的種類,然後呼叫我們設定的對應的回撥方法。
這裡值得說的是:當獲取到了 RecyclerView 的點選事件和觸控事件資料 MotionEvent,那麼如何才能知道點選的是哪一個 item 呢?
RecyclerView已經為我們提供了這樣的方法:findChildViewUnder()。
我們可以通過這個方法獲得點選的 item ,同時我們呼叫 RecyclerView 的另一個方法 getChildViewHolder(),可以獲得該 item 的 ViewHolder,最後再回撥我們定義的虛方法 onItemClick() 就ok了,這樣我們就可以在外部實現該方法來獲得 item 的點選事件了。
2
新增 divider 的標準姿勢
當你想給條目間新增 divider 時,你可能自然而然的去嘗試這種方式:
<android.support.v7.widget.RecyclerView android:divider="#ffff0000" android:dividerHeight="10dp" android:layout_width="match_parent" android:layout_height="match_parent" />
其實 RecyclerView 是沒有這兩個屬性的,就算你寫上也不會有任何效果。
當然你還可以通過給 item 的最外層佈局設定一個 margin 值,甚至你還可以專門在 item 佈局中的適當地方新增一個高度/寬度為 1 的帶背景的 View 作為 divider,這兩種方法呢,確實有效果,但是不夠優雅,有時還可能帶來一些想不到的問題。
其實官方還是為我們提供了為 RecyclerView 新增分割線的方式的,那就是方法: mRecyclerView.addItemDecoration()。
該方法的引數為 RecyclerView.ItemDecoration,該類為抽象類,且官方目前並沒有提供預設的實現類,我們只能自己來實現。
注意:作者這裡給出了列表佈局和網格佈局分別實現分割線的實現類,由於程式碼太長,可以跳轉到原文檢視。
上面給出的兩個例項都是最簡單的一條線的分割。這裡的分割線你是可以自由的去自定義它的,具體如何實現也不是太複雜,這裡不再做詳細介紹了,推薦一篇文章:
《RecyclerView之ItemDecoration 講解及高階特性實踐》
http://www.10tiao.com/html/227/201705/2650239745/1.html
3
實現 item 的拖曳排序和滑動刪除
下面就主要為大家梳理一下拖曳排序和滑動刪除的實現,具體實現效果看文章首部效果圖,這裡就不再重複放圖了。
實現方式
主要就要使用到 ItemTouchHelper,ItemTouchHelper 一個幫助開發人員處理拖拽和滑動刪除的實現類,它能夠讓你非常容易實現側滑刪除、拖拽的功能。
(ItemTouchHelper 的使用並不僅僅侷限於 RecyclerView 的滑動刪除,你同意可以用在其他需要拖曳滑動的地方。當然,今天我們不涉及其他地方的使用)
實現的程式碼並關聯到 RecyclerView 非常簡單,程式碼如下:
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback());itemTouchHelper.attachToRecyclerView(mRecyclerView);
程式碼很簡單,沒什麼好說的。
需要我們關注的是建立 ItemTouchHelper 時傳入的引數 ItemTouchHelper.Callback() 。ItemTouchHelper 會在拖拽的時候回撥 Callback 中相應的方法,我們只需在 Callback 中實現自己的邏輯。
自定義一個類繼承實現 ItemTouchHelper.Callback 介面,需要實現以下方法:
getMovementFlags() 用於設定是否處理拖拽事件和滑動事件,以及拖拽和滑動操作的方向,有以下兩種情況:
-
如果是列表型別的 RecyclerView,拖拽只有 UP、DOWN 兩個方向
-
如果是網格型別的則有 UP、DOWN、LEFT、RIGHT 四個方向
該方法需要編寫的程式碼如下:
dragFlags 是拖拽標誌,
swipeFlags 是滑動標誌,
swipeFlags 都設定為0,暫時不考慮滑動相關操作。
如果設定了相關的 dragFlags,那麼當長按 item 的時候就會進入拖拽並在拖拽過程中不斷回撥 onMove() 方法,我們就在這個方法裡獲取當前拖拽的 item 和已經被拖拽到所處位置的 item 的ViewHolder,有了這2個 ViewHolder,我們就可以交換他們的資料集並呼叫 Adapter 的notifyItemMoved 方法來重新整理 item。
只要重寫完上面這兩個方法,RecyclerView 就能實現拖曳的效果了。是不是很簡單?
但是雖然拖曳是沒什麼問題了,但是並不能達到下圖的效果,因為你正在拖曳的 item 並沒有陰影效果。
那怎麼才能實現被拖曳的 item 有背景顏色加深起到強調的視覺效果呢?這是需要重寫下面兩個方法:
這樣就能完全達到上面圖片的效果了。
滑動刪除
如何實現滑動刪除呢?我們只需要實現第三個方法 onSwipe() 就行了。
程式碼如下:
同時也不要忘了修改一下 getMovementFlags() 方法,以便能夠相應滑動事件:
那目前你就能完美的實現拖曳排序和滑動刪除了。
拖曳排序,首個固定
有時我們希望首個 item 不能被拖曳排序。比如我們在新聞 App 中常見當我們進行新聞分類時,“熱門”新聞這個分類總是第一個且不能被拖曳修改,類似下面的效果:
那麼怎麼才能達到上面的效果呢?在上面我們的 Callback 類中有一個方法:
public boolean isLongPressDragEnabled() { return true;}
這個方法是為了告訴 ItemTouchHelper 是否需要 RecyclerView 支援長按拖拽,預設返回是 ture,理所當然我們要支援,所以我們沒有重寫,因為預設true。
但是這樣做是預設全部的item都可以拖拽,怎麼實現部分item拖拽呢,在 isLongPressDragEnabled 方法的原始碼中有提示說,如果想自定義拖曳 view,那麼就使用 startDrag(ViewHolder) 方法。
第一步:那麼我們就先重寫 isLongPressDragEnabled() 方法,返回 false 讓它控制所有的 item 都不能拖曳。
public boolean isLongPressDragEnabled() { return false;}
第二步:我們給 RecyclerView 設定 item 的長按監聽事件,然後判斷這個 item 是不是第一個(或者最後一個,如果你不想讓最後一個被拖曳的話),如果不是我們就手動呼叫 startDrag(ViewHolder) 讓 item 開始被拖曳。
結合上面我們提供的給 item 設定點選和長按事件的方法,我們可以這樣:
第三步:如果你以為上面兩步你就達到首個 item 固定不被拖曳的話,恭喜你,答對了!首個 item 確實固定不能被拖曳了,可是看看下圖,就會令你大跌眼睛:
雖然我們通過上面兩步控制了首個 item 不能被長按拖曳,但是我們並沒有處理,別的 item 被拖曳到首個 item 的情況。那麼如何才能讓首個 item 不被擠掉呢,這個也很簡單,只需要在 Callback 的 onMove() 方法中處理首個 item 被當著目標 item 的情況就行了。
好了,到這裡就大功告成了。
本文原始碼地址:
https://github.com/OCNYang/RecyclerViewEvent
參考文章:
http://chuansong.me/n/400690551872
http://chuansong.me/n/400690851058
http://www.10tiao.com/html/227/201705/2650239745/1.html
相關文章
- (有圖)仿QQ側滑選單:RecyclerView側滑選單,長按拖拽,滑動刪除View
- RecyclerView-->點選和長按事件View事件
- RecyclerView使用指南(三)—— 新增分割線和點選事件View事件
- RecyclerView 實現滑動刪除和拖拽功能View
- RecyclerView實現滑動刪除和拖拽功能View
- 移動端VUE點選、滑動和長按等事件處理(自定義指令)Vue事件
- 短視訊app開發,左滑刪除或長按彈出刪除選擇框APP
- RecyclerView滑動到底部的時候點選按鈕直接返回頂部View
- 刪除按鈕點選後的虛線輪廓
- 自定義RecyclerView實現側滑刪除View
- JavaScript點選按鈕刪除div元素JavaScript
- jQuery點選按鈕刪除div元素jQuery
- Android觸控事件(續)——點選長按事件Android事件
- 短視訊系統,長按側滑實現刪除的按鈕
- RecyclerView中item點選事件View事件
- 點選刪除按鈕彈出是否刪除提示框
- 點選刪除按鈕刪除當前行程式碼例項行程
- 短視訊app製作,實現訊息列表的左滑刪除或長按刪除APP
- JavaScript點選按鈕刪除一個div元素JavaScript
- 安卓開發:listview長按進入多選刪除操作安卓View
- php短視訊原始碼,向左滑動顯示刪除按鈕PHP原始碼
- 點選圖片大圖預覽,RecyclerView + PhotoView 滑動衝突,RecyclerView不回撥SCROLL_STATE_IDLEView
- RecyclerView - 新增不同的分割線View
- [Unity UGUI]點選和長按UnityUGUI
- Android--按鈕點選事件Android事件
- 原生js多選框選中排序及刪除JS排序
- 使用介面實現RecyclerView中的item點選事件View事件
- 小程式實現長按刪除圖片
- jQuery中點選刪除,顯示是否要刪除jQuery
- 點選刪除彈出提示是否刪除程式碼
- mui 點選長按複製文字UI
- RecyclerVieW自定義華麗的分割線View
- RecyclerView 、ViewPager 左右滑動衝突Viewpager
- RecyclerView滑動距離計算View
- View 事件傳遞體系知識梳理(2) 巢狀滑動View事件巢狀
- vue 左滑刪除功能Vue
- iOS UITableView側滑刪除iOSUIView
- android 滑動刪除的listview(自定義view)AndroidView