很多時候我們需要對列表進行一些操作,比如說股票的自選列表 我們希望能夠拖拽刪除置頂等操作。在recyclerveiw 之前 我們使用listview 完成這些操作 有點點麻煩,但是在recyclerview 出來之後ItemTouchHelper類使得一切變得簡單。
先上圖看下效果
/**
* Creates an ItemTouchHelper that will work with the given Callback.
* <p>
* You can attach ItemTouchHelper to a RecyclerView via
* {@link #attachToRecyclerView(RecyclerView)}. Upon attaching, it will add an item decoration,
* an onItemTouchListener and a Child attach / detach listener to the RecyclerView.
*
* @param callback The Callback which controls the behavior of this touch helper.
*/
public ItemTouchHelper(Callback callback) {
mCallback = callback;
}
在我們創建 ItemTouchHelper 的時候 需要 傳遞一個Callback 對象。 官方的解釋是 控制觸摸事件的回調。也就是監聽我們對列表的拖拽事件。我們看看callback 中具體我們要重寫哪些回調
第一個就是 getMovementFlags 。
/**
* getMovementFlags 這個方法中我們可以設置拖拽和側滑的方向 比如說我們現在是縱向列表 拖拽 設置
* makeMovementFlags(dragFlags, 0);第一個參數是拖拽的方向 ,我們設置的是ItemTouchHelper.UP | ItemTouchHelper.DOWN
* 上或者下、因爲我們沒有側滑的需求所以swipeFlags 設置了0 如果我們的列表是網格列表 gridview
* 我們也可以根據 recyclerView.getLayoutManager() 來判斷 然後
* 設置 ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT
*
* 如果是側滑 我們需要把swipeFlags 設置成ItemTouchHelper.START | ItemTouchHelper.END
* @param recyclerView
* @param viewHolder
* @return
*/
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN ;
return makeMovementFlags(dragFlags, 0);
}
第二個方法是 onMove 每次 拖動都會觸發這個回調,每次回調我們可以在我們 adapter 中 操作我們的數據 每次拖動後我們把我們列表綁定書數組裏 數據的位置也做下調整。
/**
* 顧名思義 當我們把一個 item 從一個位置拖到另一個位置 會觸發這個回調
* @param recyclerView
* @param viewHolder ;老的 位置
* @param target 新的位置
* @return
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
interfaceTouchHelper.onItemMove(viewHolder, viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
public void onItemMove(RecyclerView.ViewHolder holder, int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(data, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(data, i, i - 1);
}
}
//刷新列表
notifyItemMoved(fromPosition, toPosition);
}
其他 需要重寫的方法
/**
* 當選中的時候對 item進行 設置效果 放大 縮小 或者高亮
* @param viewHolder
* @param actionState
*/
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
interfaceTouchHelper.onItemSelect(viewHolder);
}
super.onSelectedChanged(viewHolder,actionState);
}
/**
* 拖拽 結束後 我們 要對之前 做的 效果進行清除。 恢復正常狀態
* @param recyclerView
* @param viewHolder
*/
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (!recyclerView.isComputingLayout()) {
interfaceTouchHelper.onItemClear(viewHolder);
}
super.clearView(recyclerView,viewHolder);
}
/**
* 如果我們需要動態設置 能否拖動,則重寫 isLongPressDragEnabled()方法 動態賦值,默認是true 的
* @return
*/
@Override
public boolean isLongPressDragEnabled() {
return isDrag;
}
我們寫一個接口類 來處理選中 置頂 等 操作
public interface InterfaceOnCheckOrClickListener {
/**
* 點擊拖動
*/
void onViewDragStart(MotionEvent event);
/**
* 停止拖動
*/
void onViewDragStop();
/**
* 置頂點擊事件
* @param view
* @param position
*/
void onViewClick(View view, int position);
/**
* 選中的CheckBox
* @param view
* @param position
*/
void onCheckBoxSelected(View view, int position);
}
在我們的activity 中 繼承這個接口 重寫 onViewClick 方法
/**
* 點擊置頂
* @param view
* @param position
*/
@Override
public void onViewClick(View view, int position) {
for (int i = position; i > 0; i--) {
Collections.swap(myAdapter.getData(), i, i - 1);
}
myAdapter.notifyDataSetChanged();
}
還有一些具體的代碼實現不再贅述 直接上源碼吧。