本文实例为大家分享了RecycleView实现拖拽交换item位置的具体代码,供大家参考,具体内容如下
老规矩,先来一张效果图:
相比起ListView而言,RecycleView实现拖拽交换位置的效果要简单很多,因为通过SDK中的ItemTouchHelper工具类可以轻松的实现这种效果,并且一套代码支持所有布局方式;而ListView的话则需要通过生成View的缓存镜像设置到ImageView中,然后通过WindowManager来操作该ImageView,具体怎么实现这里就不展开讲解了.回归到ItemTouchHelper话题上,这个工具类我们需要关心的方法只有一个,即:
1
|
public
void
attachToRecyclerView(
@Nullable
RecyclerView recyclerView) {}
|
通过名字也可以知道其作用就是和RecyclerView 建立关系.
而我们真正需要关心的地方就是ItemTouchHelper的内部类ItemTouchHelper.Callback,它是一个抽象类,需要我们去实现下面这几个关键的抽象方法以及重写几个非抽象的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//决定拖拽/滑动的方向
public
abstract
int
getMovementFlags(RecyclerView recyclerView,
ViewHolder viewHolder);
//和位置交换有关,可用于实现drag功能
public
abstract
boolean
onMove(RecyclerView recyclerView,
ViewHolder viewHolder, ViewHolder target);
//和滑动有关,可用于实现swipe功能
public
abstract
void
onSwiped(ViewHolder viewHolder,
int
direction);
//是否长按启用拖拽功能,默认是true
public
boolean
isLongPressDragEnabled() {
return
true
;}
//是否支持滑动,默认true
public
boolean
isItemViewSwipeEnabled() {
return
true
;}
//和目标View的状态改变有关,例如drag,swipe,ide
public
void
onSelectedChanged(ViewHolder viewHolder,
int
actionState) {}
//和移除View的状态有关,通常用于清除在onSelectedChanged,onChildDraw中对View设置的动画
public
void
clearView(RecyclerView recyclerView, ViewHolder viewHolder) {}
|
当创建完ItemTouchHelper.Callback的实现类,我这里称之为SimpleItemTouchHelperCallback后,还需要将数据的变化以及View的状态通知到RecycleView的Adapter中,为了达到解耦的目的,通常可以通过定义接口来实现,在SimpleItemTouchHelperCallback的构造方法中传入该解耦接口的引用,并让RecycleView的Adapter实现该解耦的接口,这样就实现了这2个类的通信问题了.
来看看我定义的解耦接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/**
* 定义RecycleView的Adapter和SimpleItemTouchHelperCallback直接交互的接口方法
* Created by mChenys on 2017/2/16.
*/
public
interface
ItemTouchHelperAdapter {
//数据交换
void
onItemMove(RecyclerView.ViewHolder source, RecyclerView.ViewHolder target);
//数据删除
void
onItemDissmiss(RecyclerView.ViewHolder source);
//drag或者swipe选中
void
onItemSelect(RecyclerView.ViewHolder source);
//状态清除
void
onItemClear(RecyclerView.ViewHolder source);
}
|
完整的SimpleItemTouchHelperCallback代码如下:
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
4
|
/**
* 处理RecycleView的选中,拖拽移动,拖拽删除的实现类
* Created by mChenys on 2017/2/16.
*/
public
class
SimpleItemTouchHelperCallback
extends
ItemTouchHelper.Callback {
private
ItemTouchHelperAdapter mAdapter;
public
SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
mAdapter = adapter;
}
@Override
public
int
getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允许上下的拖动
//int dragFlags =ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //允许左右的拖动
//int swipeFlags = ItemTouchHelper.LEFT; //只允许从右向左侧滑
//int swipeFlags = ItemTouchHelper.DOWN; //只允许从上向下侧滑
//一般使用makeMovementFlags(int,int)或makeFlag(int, int)来构造我们的返回值
//makeMovementFlags(dragFlags, swipeFlags)
int
dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
//允许上下左右的拖动
return
makeMovementFlags(dragFlags,
0
);
}
@Override
public
boolean
isLongPressDragEnabled() {
return
true
;
//长按启用拖拽
}
@Override
public
boolean
isItemViewSwipeEnabled() {
return
false
;
//不启用拖拽删除
}
@Override
public
boolean
onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
//通过接口传递拖拽交换数据的起始位置和目标位置的ViewHolder
mAdapter.onItemMove(source, target);
return
true
;
}
@Override
public
void
onSwiped(RecyclerView.ViewHolder viewHolder,
int
direction) {
//移动删除回调,如果不用可以不用理
// mAdapter.onItemDissmiss(viewHolder);
}
@Override
public
void
onSelectedChanged(RecyclerView.ViewHolder viewHolder,
int
actionState) {
super
.onSelectedChanged(viewHolder, actionState);
if
(actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
//当滑动或者拖拽view的时候通过接口返回该ViewHolder
mAdapter.onItemSelect(viewHolder);
}
}
@Override
public
void
clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super
.clearView(recyclerView, viewHolder);
if
(!recyclerView.isComputingLayout()) {
//当需要清除之前在onSelectedChanged或者onChildDraw,onChildDrawOver设置的状态或者动画时通过接口返回该ViewHolder
mAdapter.onItemClear(viewHolder);
}
}
}
|
RecycleView.Adapter实现类代码
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
|
/**
* Created by mChenys on 2017/2/15.
*/
public
class
MyAdapter
extends
RecyclerView.Adapter<MyAdapter.MyViewHolder>
implements
ItemTouchHelperAdapter {
...
@Override
public
MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int
viewType) {
...
}
@Override
public
void
onBindViewHolder(
final
MyAdapter.MyViewHolder holder,
int
position) {
...
}
@Override
public
int
getItemCount() {
//注意:这里最少有一个,因为有多了一个添加按钮
return
null
== mData ?
1
: mData.size() +
1
;
}
@Override
public
void
onItemMove(RecyclerView.ViewHolder source,
RecyclerView.ViewHolder target) {
int
fromPosition = source.getAdapterPosition();
int
toPosition = target.getAdapterPosition();
if
(fromPosition < mData.size() && toPosition < mData.size()) {
//交换数据位置
Collections.swap(mData, fromPosition, toPosition);
//刷新位置交换
notifyItemMoved(fromPosition, toPosition);
}
//移动过程中移除view的放大效果
onItemClear(source);
}
@Override
public
void
onItemDissmiss(RecyclerView.ViewHolder source) {
int
position = source.getAdapterPosition();
mData.remove(position);
//移除数据
notifyItemRemoved(position);
//刷新数据移除
}
@Override
public
void
onItemSelect(RecyclerView.ViewHolder viewHolder) {
//当拖拽选中时放大选中的view
viewHolder.itemView.setScaleX(
1
.2f);
viewHolder.itemView.setScaleY(
1
.2f);
}
@Override
public
void
onItemClear(RecyclerView.ViewHolder viewHolder) {
//拖拽结束后恢复view的状态
viewHolder.itemView.setScaleX(
1
.0f);
viewHolder.itemView.setScaleY(
1
.0f);
}
public
class
MyViewHolder
extends
RecyclerView.ViewHolder {
...
public
MyViewHolder(View itemView) {
super
(itemView);
...
}
}
}
|
MainActivity的使用方式
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
|
/**
* Created by mChenys on 2017/2/16.
*/
public
class
MainActivity
extends
AppCompatActivity {
...
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
...
mRecyclerView = (RecyclerView) findViewById(R.id.recycleView);
//创建adapter
MyAdapter myAdapter =
new
MyAdapter(
this
, mData);
//设置默认的布局方式
mRecyclerView.setLayoutManager(
new
LinearLayoutManager(
this
, LinearLayoutManager.VERTICAL,
false
));
//设置adapter
mRecyclerView.setAdapter(myAdapter);
//创建SimpleItemTouchHelperCallback
ItemTouchHelper.Callback callback =
new
SimpleItemTouchHelperCallback(myAdapter);
//用Callback构造ItemtouchHelper
ItemTouchHelper touchHelper =
new
ItemTouchHelper(callback);
//调用ItemTouchHelper的attachToRecyclerView方法建立联系
touchHelper.attachToRecyclerView(mRecyclerView);
}
@Override
public
boolean
onCreateOptionsMenu(Menu menu) {
...
return
super
.onCreateOptionsMenu(menu);
}
@Override
public
boolean
onOptionsItemSelected(MenuItem item) {
...
return
super
.onOptionsItemSelected(item);
}
}
错误解决方法
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details -> def requested = details.requested if (requested.group == 'com.android.support') { if (!requested.name.startsWith("multidex")) { details.useVersion '25.3.0' } } } } |