Android ItemTouchHelper 实践

实现RecyclerView拖动排序和滑动删除,我想到的是 ViewDragHelper ,或者是第三方库,当我看了 ToDoList 的时候,发现原来官方已经支持RecyclerView拖动排序与滑动删除,那就是ItemTouchHelper。

简介

“ItemTouchHelper is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.

It works with a RecyclerView and a Callback class, which configures what type of interactions are enabled and also receives events when user performs these actions.

Depending on which functionality you support, you should override onMove(RecyclerView, ViewHolder, ViewHolder) and / or onSwiped(ViewHolder, int).”

ItemTouchHelper 实现RecyclerView拖动排序和滑动删除,我们需要重写方法:

1
int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)

指定可以支持的拖放和滑动的方向,上下为拖动(drag),左右为滑动(swipe)

1
onMove(RecyclerView, ViewHolder, ViewHolder)

滑动操作

1
onSwiped(ViewHolder, int)

删掉操作

实践

依赖

app/build.gradle

1
compile 'com.android.support:recyclerview-v7:25.0.0'

效果预览

线性

网格

ItemTouchHelperCallback

新建ItemTouchHelperCallback继承ItemTouchHelper.Callback,完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
public class ItemTouchHelperCallback extends ItemTouchHelper.Callback {
private ItemTouchHelperAdapter itemTouchHelperAdapter;
private float ALPHA_FULL = 1.0f;
ItemTouchHelperCallback(ItemTouchHelperAdapter itemTouchHelperAdapter) {
this.itemTouchHelperAdapter = itemTouchHelperAdapter;
}
/**
* RecyclerView item支持长按进入拖动操作
*/
@Override
public boolean isLongPressDragEnabled() {
return true;
}
/**
* RecyclerView item任意位置触发启用滑动操作
*/
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
/**
* 指定可以支持的拖放和滑动的方向,上下为拖动(drag),左右为滑动(swipe)
*/
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (recyclerView.getLayoutManager() instanceof GridLayoutManager || recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager) {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
//不需要滑动
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
} else {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
}
/**
* 滑动操作
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
if (viewHolder.getItemViewType() != target.getItemViewType()) {
return false;
}
// Notify the adapter of the move
itemTouchHelperAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
/**
* 删掉操作
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
itemTouchHelperAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
//自定义滑动动画
final float alpha = ALPHA_FULL - Math.abs(dX) / (float) viewHolder.itemView.getWidth();
viewHolder.itemView.setAlpha(alpha);
viewHolder.itemView.setTranslationX(dX);
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
// We only want the active item to change
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Let the view holder know that this item is being moved or dragged
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
//选中状态回调
itemViewHolder.onItemSelected();
}
}
super.onSelectedChanged(viewHolder, actionState);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(ALPHA_FULL);
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Tell the view holder it's time to restore the idle state
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
//未选中状态回调
itemViewHolder.onItemClear();
}
}
}

attachToRecyclerView

创建ItemTouchHelper对象,然后调用attachToRecyclerView(RecyclerView) 方法

1
2
3
ItemTouchHelperCallback itemTouchHelperCallback = new ItemTouchHelperCallback(recyclerViewAdatper);
itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);

源码

更多详见源码:https://github.com/WuXiaolong/AndroidSamples/ ,很多参考了iPaulPro/Android-ItemTouchHelper-Demo,关键需要消化,转化成自己的东西。

参考

官网Api
Drag and Swipe with RecyclerView
Drag and Swipe with RecyclerView—Part Two



联系作者

我的微信公众号:吴小龙同学,欢迎关注交流,公号回复关键字「1024」有惊喜哦。