RecyclerView实现条目Item拖拽排序与滑动删除
2017-05-23 20:04
441 查看
转载地址:http://blog.csdn.net/yanzhenjie1003/article/details/51935982
版权声明:转载请注明本文转自严振杰的博客: http://blog.csdn.net/yanzhenjie1003
欢迎使用我的另一个更强大的库:RecyclerView侧滑菜单,长按拖拽,滑动删除,下拉刷新上拉加载。
直播视频讲解:[http://pan.baidu.com/s/1miEOtwG1
推荐大家结合我直播的视频看效果更好。
本博客源码传送门。
RecyclerView侧滑菜单
RecyclerView滑动删除
RecyclerView长按拖拽
RecyclerView下拉刷新上拉加载,请看下面这篇博客:
http://blog.csdn.net/yanzhenjie1003/article/details/52115566
RecyclerView Item拖拽排序::长按
RecyclerView Item滑动删除:RecyclerView Item滑动删除:
利用ItemTouchHelper绑定
继承抽象类
recyclerView绑定ItemTouchHelper:
自定义
activity_main.xml
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
这个没啥好说的了吧,就是一个
接下来是
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
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
这个也不用解释了,到时候下载看源码,就是普通item,展示数据而已。
2
3
4
5
1
2
3
4
5
好嘛,这个太简单了,基本上一行代码都不用写。但是这里需要一个
这里是全文最重要的部分啦,要认真点看噢,先上代码,后解释,其他看注释和视频。
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
好,其实上面最重要的就是五个方法:
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
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
我们记得上面定义了一个
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
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
现在我们看到已经不需要传
这里可以有的同学会有疑问,上面原来不是继承
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
好扯淡也扯完了,封装也封装完了,那么接下来就来在
没啥好说的用
2
3
4
1
2
3
4
看到上面还缺少一个
我们在自定义
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
到这里就结束了,不信你去试试,源码传送门。
RecyclerView实现条目Item拖拽排序与滑动删除
版权声明:转载请注明本文转自严振杰的博客: http://blog.csdn.net/yanzhenjie1003欢迎使用我的另一个更强大的库:RecyclerView侧滑菜单,长按拖拽,滑动删除,下拉刷新上拉加载。
效果演示
直播视频讲解:[http://pan.baidu.com/s/1miEOtwG1
推荐大家结合我直播的视频看效果更好。
本博客源码传送门。
RecyclerView侧滑菜单
RecyclerView滑动删除
RecyclerView长按拖拽
RecyclerView下拉刷新上拉加载,请看下面这篇博客:
http://blog.csdn.net/yanzhenjie1003/article/details/52115566
需求和技术分析
RecyclerView Item拖拽排序::长按RecyclerView的Item或者触摸Item的某个按钮。
RecyclerView Item滑动删除:RecyclerView Item滑动删除:
RecyclerView的Item滑动删除。
实现方案与技术
利用ItemTouchHelper绑定RecyclerView、
ItemTouchHelper.Callback来实现UI更新,并且实现动态控制是否开启拖拽功能和滑动删除功能。
实现步骤
继承抽象类ItemTouchHelper,并在构造方法传入实现的
ItemTouchHelper.Callback。
recyclerView绑定ItemTouchHelper:
itemTouchHelper.attachToRecyclerView(recyclerView)。
自定义
ItemTouchHelper.Callback的实现接口
OnItemTouchCallbackListener,由外部更新
RecyclerView的Item。
几个主要的布局
activity_main.xml<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/rv_main" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
这个没啥好说的了吧,就是一个
RecyclerView啦。
接下来是
RecyclerView的Item的布局item.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="?android:listPreferredItemHeight" android:background="?selectableItemBackground"> <ImageView android:id="@+id/iv_touch" style="@style/ItemStyle" android:layout_height="match_parent" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:src="@android:drawable/alert_dark_frame" /> <CheckBox android:id="@+id/cb_item_check" style="@style/ItemStyle" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <TextView android:id="@+id/tv_name" style="@style/ItemStyle" android:layout_toEndOf="@id/cb_item_check" android:layout_toRightOf="@id/cb_item_check" /> <TextView android:id="@+id/tv_sex" style="@style/ItemStyle" android:layout_marginLeft="@dimen/dp_10" android:layout_marginStart="@dimen/dp_10" android:layout_toEndOf="@id/tv_name" android:layout_toRightOf="@id/tv_name" /> </RelativeLayout>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
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
这个也不用解释了,到时候下载看源码,就是普通item,展示数据而已。
实现自己的DefaultItemTouchHelper
:继承ItemTouchHelper
public class DefaultItemTouchHelper extends ItemTouchHelper { public DefaultItemTouchHelper(ItemTouchHelp.Callback callback) { super(callback); } }1
2
3
4
5
1
2
3
4
5
好嘛,这个太简单了,基本上一行代码都不用写。但是这里需要一个
ItemTouchHelp.Callback啊,所以我们还是要实现一个
ItemTouchHelp.Callback,客观且看下文分解。
实现自己的ItemTouchHelper.Callback
:继承ItemTouchHelper.Callback
这里是全文最重要的部分啦,要认真点看噢,先上代码,后解释,其他看注释和视频。public class DefaultItemTouchHelpCallback extends ItemTouchHelper.Callback { /** * Item操作的回调 */ private OnItemTouchCallbackListener onItemTouchCallbackListener; /** * 是否可以拖拽 */ private boolean isCanDrag = false; /** * 是否可以被滑动 */ private boolean isCanSwipe = false; public DefaultItemTouchHelpCallback(OnItemTouchCallbackListener onItemTouchCallbackListener) { this.onItemTouchCallbackListener = onItemTouchCallbackListener; } /** * 设置Item操作的回调,去更新UI和数据源 * * @param onItemTouchCallbackListener */ public void setOnItemTouchCallbackListener(OnItemTouchCallbackListener onItemTouchCallbackListener) { this.onItemTouchCallbackListener = onItemTouchCallbackListener; } /** * 设置是否可以被拖拽 * * @param canDrag 是true,否false */ public void setDragEnable(boolean canDrag) { isCanDrag = canDrag; } /** * 设置是否可以被滑动 * * @param canSwipe 是true,否false */ public void setSwipeEnable(boolean canSwipe) { isCanSwipe = canSwipe; } /** * 当Item被长按的时候是否可以被拖拽 * * @return */ @Override public boolean isLongPressDragEnabled() { return isCanDrag; } /** * Item是否可以被滑动(H:左右滑动,V:上下滑动) * * @return */ @Override public boolean isItemViewSwipeEnabled() { return isCanSwipe; } /** * 当用户拖拽或者滑动Item的时候需要我们告诉系统滑动或者拖拽的方向 * * @param recyclerView * @param viewHolder * @return */ @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) {// GridLayoutManager // flag如果值是0,相当于这个功能被关闭 int dragFlag = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT | ItemTouchHelper.UP | ItemTouchHelper.DOWN; int swipeFlag = 0; // create make return makeMovementFlags(dragFlag, swipeFlag); } else if (layoutManager instanceof LinearLayoutManager) {// linearLayoutManager LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager; int orientation = linearLayoutManager.getOrientation(); int dragFlag = 0; int swipeFlag = 0; // 为了方便理解,相当于分为横着的ListView和竖着的ListView if (orientation == LinearLayoutManager.HORIZONTAL) {// 如果是横向的布局 swipeFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN; dragFlag = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; } else if (orientation == LinearLayoutManager.VERTICAL) {// 如果是竖向的布局,相当于ListView dragFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN; swipeFlag = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; } return makeMovementFlags(dragFlag, swipeFlag); } return 0; } /** * 当Item被拖拽的时候被回调 * * @param recyclerView recyclerView * @param srcViewHolder 拖拽的ViewHolder * @param targetViewHolder 目的地的viewHolder * @return */ @Override public boolean onMove(RecyclerView recyclerView, ViewHolder srcViewHolder, ViewHolder targetViewHolder) { if (onItemTouchCallbackListener != null) { return onItemTouchCallbackListener.onMove(srcViewHolder.getAdapterPosition(), targetViewHolder.getAdapterPosition()); } return false; } @Override public void onSwiped(ViewHolder viewHolder, int direction) { if (onItemTouchCallbackListener != null) { onItemTouchCallbackListener.onSwiped(viewHolder.getAdapterPosition()); } } public interface OnItemTouchCallbackListener { /** * 当某个Item被滑动删除的时候 * * @param adapterPosition item的position */ void onSwiped(int adapterPosition); /** * 当两个Item位置互换的时候被回调 * * @param srcPosition 拖拽的item的position * @param targetPosition 目的地的Item的position * @return 开发者处理了操作应该返回true,开发者没有处理就返回false */ boolean onMove(int srcPosition, int targetPosition); } }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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
好,其实上面最重要的就是五个方法:
/** * 是否可以长按拖拽排序。 */ @Override public boolean isLongPressDragEnabled() {} /** * Item是否可以被滑动(H:左右滑动,V:上下滑动) */ @Override public boolean isItemViewSwipeEnabled() {} /** * 当用户拖拽或者滑动Item的时候需要我们告诉系统滑动或者拖拽的方向 */ @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {} /** * 当Item被拖拽的时候被回调 */ @Override public boolean onMove(RecyclerView r, ViewHolder rholer, ViewHolder tholder) {} /** * 当View被滑动删除的时候 */ @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {}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
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
isItemViewSwipeEnabled()返回值是否可以拖拽排序,true可以,false不可以,
isItemViewSwipeEnabled()是否可以滑动删除,true可以,false不可以;这两个方法都是配置是否可以操作的。我们上面的代码中返回了一个成员变量值,并且这个值通过外部可以修改,所以提供了外部控制的方法。
onMove()当Item被拖拽排序移动到另一个Item的位置的时候被回调,
onSwiped()当Item被滑动删除到不见;这两个方法是当用户操作了,来回调我们,我们就该去更新UI了。这里我们提供了一个Listener去通知外部,并且返回出去了必要的值,来降低代码耦合度。
getMovementFlags()说明一:是当用户拖拽或者滑动Item的时候需要我们告诉系统滑动或者拖拽的方向,那我们又知道支持拖拽和滑动删除的无非就是
LinearLayoutManager和
GridLayoutManager了,相当于我们老早的时候用的
ListView和
GridView了。所以我们根据布局管理器的不同做了响应的区分。
getMovementFlags()说明二:其他都好理解,就是这里的
return makeMovementFlags(dragFlag, swipeFlag);这句话是最终的返回值,也就是它决定了我们的拖拽或者滑动的方法。第一个参数是拖拽flag,第二个是滑动的flag。
重新定义DefaultItemTouchHelper
我们记得上面定义了一个DefaultItemTouchHelper,它的构造中需要传一个
ItemTouchHelper.Callback,既然我们实现礼了,我们再把
DefaultItemTouchHelper做个封装,使使用者更傻瓜式的调用。
public class DefaultItemTouchHelper extends YolandaItemTouchHelper { private DefaultItemTouchHelpCallback itemTouchHelpCallback; public DefaultItemTouchHelper(DefaultItemTouchHelpCallback.OnItemTouchCallbackListener onItemTouchCallbackListener) { super(new DefaultItemTouchHelpCallback(onItemTouchCallbackListener)); itemTouchHelpCallback = (DefaultItemTouchHelpCallback) getCallback(); } /** * 设置是否可以被拖拽 * * @param canDrag 是true,否false */ public void setDragEnable(boolean canDrag) { itemTouchHelpCallback.setDragEnable(canDrag); } /** * 设置是否可以被滑动 * * @param canSwipe 是true,否false */ public void setSwipeEnable(boolean canSwipe) { itemTouchHelpCallback.setSwipeEnable(canSwipe); } }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
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
现在我们看到已经不需要传
ItemTouchHelper.Callback给
ItemTouchHelper了,只需要传我们在
DefaultItemTouchHelpCallback中定义好的
OnItemTouchCallbackListener就好了,而且提供了设置是否可以滑动和是否可以拖拽的方法,而
OnItemTouchCallbackListener只是通知外部滑动了、删除了,你去更新UI吧。
这里可以有的同学会有疑问,上面原来不是继承
ItemTouchHelper吗?这里咋就变成了
YolandaItemTouchHelper了呢?因为我们看到这里多了一句
itemTouchHelpCallback = getCallback();,这个
getCallback();这个方法是没有的,是我们在
YolandaItemTouchHelper中自定义的,因为我们想在
DefaultItemTouchHelper中提供外部设置是否可以拖拽和滑动删除的方法,就得拿到这个
Callback,所以我看了下源码,我们在
ItemTouchHelper构造中把
Callback穿进去,它保存的时候一个package级别的成员变量,所以我在
Android.support.v7.widget.helper包下新建了一个
YolandaItemTouchHelper类:
public class YolandaItemTouchHelper extends ItemTouchHelper { public YolandaItemTouchHelper(Callback callback) { super(callback); } public Callback getCallback() { return mCallback; } }1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
如何投入使用
好扯淡也扯完了,封装也封装完了,那么接下来就来在Activity中使用下咯:
recyclerView绑定ItemTouchHelper
没啥好说的用itemTouchHelper.attachToRecyclerView(recyclerView)绑定
recyclerView和
ItemTouchHelper,并且只是允许拖拽和滑动删除Item:
DefaultItemTouchHelper itemTouchHelper = new DefaultItemTouchHelper(onItemTouchCallbackListener); itemTouchHelper.attachToRecyclerView(recyclerView); itemTouchHelper.setDragEnable(true); itemTouchHelper.setSwipeEnable(true);1
2
3
4
1
2
3
4
看到上面还缺少一个
onItemTouchCallbackListener吧,这个也比较重要。
使用Callback
自定义的OnItemTouchCallbackListener
刷新UI
我们在自定义Callback的时候不是在
onMove()和
onSwiped()方法中回调
OnItemTouchCallbackListener去更新UI吗?这里就是
OnItemTouchCallbackListener如何更新UI的操作了,完成这个操作,那么我们的目的就达到了:
private DefaultItemTouchHelpCallback.OnItemTouchCallbackListener onItemTouchCallbackListener = new DefaultItemTouchHelpCallback.OnItemTouchCallbackListener() { @Override public void onSwiped(int adapterPosition) { // 滑动删除的时候,从数据源移除,并刷新这个Item。 if (userInfoList != null) { userInfoList.remove(adapterPosition); mainAdapter.notifyItemRemoved(adapterPosition); } } @Override public boolean onMove(int srcPosition, int targetPosition) { if (userInfoList != null) { // 更换数据源中的数据Item的位置 Collections.swap(userInfoList, srcPosition, targetPosition); // 更新UI中的Item的位置,主要是给用户看到交互效果 mainAdapter.notifyItemMoved(srcPosition, targetPosition); return true; } return false; } };1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
到这里就结束了,不信你去试试,源码传送门。
相关文章推荐
- RecyclerView实现条目Item拖拽排序与滑动删除
- RecyclerView实现条目Item拖拽排序与滑动删除
- android RecyclerView实现条目Item拖拽排序与滑动删除
- RecyclerView实现条目Item拖拽排序与滑动删除
- RecyclerView实现条目Item拖拽排序与滑动删除
- 使用ItemTouchHelper轻松实现RecyclerView拖拽排序和滑动删除
- 使用ItemTouchHelper轻松实现RecyclerView拖拽排序和滑动删除
- RecyclerView拖拽排序和滑动删除实现
- RecyclerView搭配ItemTouchHelper实现长按拖拽、滑动删除
- ItemTouchHelper实现RecylerView的拖拽以及滑动删除功能
- Android LRecyclerView实现Item侧滑菜单、长按拖拽Item、滑动删除Item等功能
- RecyclerView学习--item实现拖拽和滑动删除
- ItemTouchHelper实现滑动删除和长按拖拽功能
- Android学习之ItemTouchHelper实现RecylerView的拖拽以及滑动删除功能
- RecyclerView之使用ItemTouchHelper和ItemTouchHelper.Callback实现条目拖拽排序
- Android学习之ItemTouchHelper实现RecylerView的拖拽以及滑动删除功能
- [置顶] Android LRecyclerView实现Item侧滑菜单、长按拖拽Item、滑动删除Item等功能
- ItemTouchHelper实现RecyclerView拖动排序和滑动删除
- recyclerview实现拖拽排序和侧滑删除
- Android学习之ItemTouchHelper实现RecylerView的拖拽以及滑动删除功能