android-AdvancedRecyclerview

演示地址(需梯子):
https://www.youtube.com/watch?feature=player_embedded&v=S7cSwMArjUQ


今天主要使用这个库来实现**RecyclerView** 的**左右滑动item **拖拽排序

效果图
Gradle配置

1
2
compile 'com.android.support:recyclerview-v7:22.1.1'
compile 'com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.7.1'

接下来我们就可以使用了

####1. 在布局中添加**RecyclerView**控件

1
2
3
4
5
6
7
8
9
10
11
12
<!-- activity_main.xml -->

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://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/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

####2. 初始化**RecyclerView**

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
//MainActivity

public class MainActivity extends AppCompatActivity {

private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private RecyclerView.Adapter mAdapter;
private RecyclerView.Adapter mWrappedAdapter;
private RecyclerViewSwipeManager mRecyclerViewSwipeManager;
private RecyclerViewTouchActionGuardManager mRecyclerViewTouchActionGuardManager;
private RecyclerViewDragDropManager mRecyclerViewDragDropManager;

private List<MyItem> dataList = new ArrayList<>();


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//获取RecycleView,创建LayoutManager
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mLayoutManager = new LinearLayoutManager(this);

// touch guard manager 阻止当左右滑动(swipe)item时列表滚动
mRecyclerViewTouchActionGuardManager = new RecyclerViewTouchActionGuardManager();
mRecyclerViewTouchActionGuardManager.setInterceptVerticalScrollingWhileAnimationRunning(true);
mRecyclerViewTouchActionGuardManager.setEnabled(true);

// drag & drop manager 拖拽排序的manager
mRecyclerViewDragDropManager = new RecyclerViewDragDropManager();
mRecyclerViewDragDropManager.setDraggingItemShadowDrawable(
(NinePatchDrawable) getResources().getDrawable(R.drawable.material_shadow_z3_xxhdpi));

// swipe manager 滑动item的manager
mRecyclerViewSwipeManager = new RecyclerViewSwipeManager();

//adapter,这里是模拟数据
for(int i=0;i<100;i++){
dataList.add(new MyItem(i,"测试数据"+i));
}
mAdapter = new MyAdapter(dataList);

//封装一下adapter
mWrappedAdapter = mRecyclerViewDragDropManager.createWrappedAdapter(mAdapter); //处理一下mAdapter可以拖拽
mWrappedAdapter = mRecyclerViewSwipeManager.createWrappedAdapter(mWrappedAdapter); //处理一下mAdapter可以滑动删除,注意这里的 -变量


final GeneralItemAnimator animator = new SwipeDismissItemAnimator();

// Change animations are enabled by default since support-v7-recyclerview v22.
// Disable the change animation in order to make turning back animation of swiped item works properly.
animator.setSupportsChangeAnimations(false);

mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mWrappedAdapter); // 注意设置的是mWrappedAdapter
mRecyclerView.setItemAnimator(animator);

//additional decorations
//noinspection StatementWithEmptyBody
if (supportsViewElevation()) {
// Lollipop or later has native drop shadow feature. ItemShadowDecorator is not required.
} else {
mRecyclerView.addItemDecoration(new ItemShadowDecorator((NinePatchDrawable) getResources().getDrawable(R.drawable.material_shadow_z3_xxhdpi)));
}
mRecyclerView.addItemDecoration(new SimpleListDividerDecorator(getResources().getDrawable(R.drawable.list_divider), true));

// NOTE:
// 初始化的顺序十分重要,这决定了处理Touch事件的优先级
// 优先级: TouchActionGuard > Swipe > DragAndDrop
mRecyclerViewTouchActionGuardManager.attachRecyclerView(mRecyclerView);
mRecyclerViewSwipeManager.attachRecyclerView(mRecyclerView);
mRecyclerViewDragDropManager.attachRecyclerView(mRecyclerView);

}

//判断版本号
private boolean supportsViewElevation() {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP);
}

}

需要注意的问题

  1. adapter的处理
  2. 需要将需要用到的manager 绑定到recylerView

3. 最主要的还是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
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
//MyAdapter

/*
* Created by Hanks
* Copyright (c) 2015 Nashangban. All rights reserved
*
*/
package app.hanks.com.testadvancerecyclerview;

import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange;
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractDraggableSwipeableItemViewHolder;

import java.util.List;

/**
* Created by Hanks on 2015/5/24.
*/
public class MyAdapter
extends RecyclerView.Adapter<MyAdapter.MyViewHolder>
implements DraggableItemAdapter<MyAdapter.MyViewHolder>,
SwipeableItemAdapter<MyAdapter.MyViewHolder> {


private final List<MyItem> dataList;

public MyAdapter( List<MyItem> dataList) {
this.dataList = dataList;
//需要设置id
setHasStableIds(true);
}

//需要设置Id
@Override
public long getItemId(int position) {
return dataList.get(position).getId();
}

@Override
public int getItemViewType(int position) {
return dataList.get(position).getViewType();
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View v = inflater.inflate(R.layout.item_list_swipe, parent, false);
return new MyViewHolder(v);
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {


MyItem item = dataList.get(position);
holder.textView.setText(item.getContent());

// set background resource (target view ID: container)
final int dragState = holder.getDragStateFlags();
final int swipeState = holder.getSwipeStateFlags();

if (((dragState & RecyclerViewDragDropManager.STATE_FLAG_IS_UPDATED) != 0) ||
((swipeState & RecyclerViewSwipeManager.STATE_FLAG_IS_UPDATED) != 0)) {
int bgResId;

if ((dragState & RecyclerViewDragDropManager.STATE_FLAG_IS_ACTIVE) != 0) {
bgResId = R.drawable.bg_item_dragging_active_state;
} else if ((dragState & RecyclerViewDragDropManager.STATE_FLAG_DRAGGING) != 0) {
bgResId = R.drawable.bg_item_dragging_state;
} else if ((swipeState & RecyclerViewSwipeManager.STATE_FLAG_IS_ACTIVE) != 0) {
bgResId = R.drawable.bg_item_swiping_active_state;
} else if ((swipeState & RecyclerViewSwipeManager.STATE_FLAG_SWIPING) != 0) {
bgResId = R.drawable.bg_item_swiping_state;
} else {
bgResId = R.drawable.bg_item_normal_state;
}

holder.container.setBackgroundResource(bgResId);
}

// set swiping properties
holder.setSwipeItemSlideAmount(
item.isPinedToSwipeLeft() ? RecyclerViewSwipeManager.OUTSIDE_OF_THE_WINDOW_LEFT : 0);
}

@Override
public int getItemCount() {
return dataList.size();
}

//交换位置
@Override
public void onMoveItem(int fromPosition, int toPosition) {
Log.d("zyh", "onMoveItem(fromPosition = " + fromPosition + ", toPosition = " + toPosition + ")");

if (fromPosition == toPosition) {
return;
}
moveItem(fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}

private void moveItem(int fromPosition, int toPosition) {
if (fromPosition == toPosition) {
return;
}
final MyItem item = dataList.remove(fromPosition);
dataList.add(toPosition, item);
}

@Override
public int onGetSwipeReactionType(MyViewHolder holder, int position, int x, int y) {
if (onCheckCanStartDrag(holder, position, x, y)) {
return RecyclerViewSwipeManager.REACTION_CAN_NOT_SWIPE_BOTH;
} else {
return RecyclerViewSwipeManager.REACTION_CAN_SWIPE_BOTH;
}
}

@Override
public void onSetSwipeBackground(MyViewHolder holder, int position, int type) {
int bgRes = 0;
switch (type) {
case RecyclerViewSwipeManager.DRAWABLE_SWIPE_NEUTRAL_BACKGROUND:
bgRes = R.drawable.bg_swipe_item_neutral;
break;
case RecyclerViewSwipeManager.DRAWABLE_SWIPE_LEFT_BACKGROUND:
bgRes = R.drawable.bg_swipe_item_left; //左边滑动出现的布局,应该算是一个drawable
break;
case RecyclerViewSwipeManager.DRAWABLE_SWIPE_RIGHT_BACKGROUND:
bgRes = R.drawable.bg_swipe_item_right; //右边滑动出现的布局
break;
}
holder.itemView.setBackgroundResource(bgRes);
}

@Override
public int onSwipeItem(MyViewHolder holder, int position, int result) {
switch (result) {
// swipe right
case RecyclerViewSwipeManager.RESULT_SWIPED_RIGHT:
if (dataList.get(position).isPinedToSwipeLeft()) {
// pinned --- back to default position
return RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_DEFAULT;
} else {
// not pinned --- remove
return RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_REMOVE_ITEM;
}
// swipe left -- pin
case RecyclerViewSwipeManager.RESULT_SWIPED_LEFT:
return RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_MOVE_TO_SWIPED_DIRECTION;
// other --- do nothing
case RecyclerViewSwipeManager.RESULT_CANCELED:
default:
return RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_DEFAULT;
}
}

@Override
public void onPerformAfterSwipeReaction(MyViewHolder holder, int position, int result, int reaction) {
final MyItem item = dataList.get(position);
if (reaction == RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_REMOVE_ITEM) {
dataList.remove(position);
notifyItemRemoved(position);
} else if (reaction == RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_MOVE_TO_SWIPED_DIRECTION) {
item.setPinedToSwipeLeft(true);
notifyItemChanged(position);

} else {
item.setPinedToSwipeLeft(false);
}
}


@Override
public boolean onCheckCanStartDrag(MyViewHolder holder, int position, int x, int y) {
// x, y --- relative from the itemView's top-left
final View containerView = holder.container;
final View dragHandleView = holder.dragHandle;

final int offsetX = containerView.getLeft() + (int) (ViewCompat.getTranslationX(containerView) + 0.5f);
final int offsetY = containerView.getTop() + (int) (ViewCompat.getTranslationY(containerView) + 0.5f);

return hitTest(dragHandleView, x - offsetX, y - offsetY);
}

@Override
public ItemDraggableRange onGetItemDraggableRange(MyViewHolder holder, int position) {
// no drag-sortable range specified
return null;
}


public static class MyViewHolder extends AbstractDraggableSwipeableItemViewHolder {

private final ViewGroup container;
private final TextView textView;
private final View dragHandle;

public MyViewHolder(View itemView) {
super(itemView);
container = (ViewGroup) itemView.findViewById(R.id.container);
dragHandle = itemView.findViewById(R.id.drag_handle);
textView = (TextView) itemView.findViewById(R.id.text);
}

@Override
public View getSwipeableContainerView() {
return container;
}
}

public static boolean hitTest(View v, int x, int y) {
final int tx = (int) (ViewCompat.getTranslationX(v) + 0.5f);
final int ty = (int) (ViewCompat.getTranslationY(v) + 0.5f);
final int left = v.getLeft() + tx;
final int right = v.getRight() + tx;
final int top = v.getTop() + ty;
final int bottom = v.getBottom() + ty;

return (x >= left) && (x <= right) && (y >= top) && (y <= bottom);
}
}

####4. 还没完, item的布局

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
<!-- item_list_swipe -->
<?xml version="1.0" encoding="utf-8"?>

<!-- NOTE: should use FrameLayout or RelativeLayout for parent of the "@id/container" view (for Android 2.3 compatibility) -->
<FrameLayout
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="64dp"
android:minHeight="64dp"
android:background="@drawable/bg_swipe_item_neutral">

<RelativeLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
tools:ignore="UselessParent">

<View
android:id="@+id/drag_handle"
android:layout_width="32dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#20000000"/>

<TextView
android:id="@+id/text"
android:text="sdsad"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@id/drag_handle"
android:gravity="center"
tools:ignore="RtlHardcoded"/>
</RelativeLayout>

</FrameLayout>

注意上面的布局

Demo: https://github.com/hanks-zyh/RecylerView

library: https://github.com/h6ah4i/android-advancedrecyclerview