本文將帶你一步一步的實(shí)現(xiàn)recyclerview的拖動(dòng)排序與側(cè)滑刪除
效果圖如下:

有圖有真相.gif
接下來(lái)就開始動(dòng)手啦!
先加入包吧
compile 'com.android.support:recyclerview-v7:25.3.0'
compile 'com.android.support:cardview-v7:25.3.0'
在activity_main.xml文件中只有一個(gè)RecyclerView
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
子布局item_rv.xml只有一個(gè)TextView
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:minHeight="40dp"
android:id="@+id/card"
app:cardCornerRadius="5dp"
>
<TextView
android:id="@+id/title"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="23sp"
android:text="title"/>
</android.support.v7.widget.CardView>
接下來(lái)為Recyclerview定義一個(gè)Adapter并且繼承自RecyclerView.Adapter
public class RvAdapter extends RecyclerView.Adapter<RvAdapter.ViewHolder> {
private List<String> mData;
public List<String> getDataList(){
return mData;
}
public RvAdapter(List<String> mData) {
this.mData
= mData;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater
.from(parent.getContext())
.inflate(R.layout.item_rv, null);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ViewHolder mHolder = holder;
mHolder.title.setText(mData.get(position));
}
@Override
public int getItemCount() {
return mData.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView title;
public ViewHolder(View itemView) {
super(itemView);
title= (TextView) itemView.findViewById(R.id.title);
}
}
public void onItemDissmiss(int position) {
//移除數(shù)據(jù)
mData.remove(position);
notifyItemRemoved(position);
}
}
在MainActivity里面找到RecyclerView并且設(shè)置它的layoutManager和Adapter,這樣就完成了一個(gè)列表
rv= (RecyclerView) findViewById(R.id.rv);
LinearLayoutManager layoutManager=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
// GridLayoutManager layoutManager=new GridLayoutManager(this,3,GridLayoutManager.VERTICAL,false);
RvAdapter adapter=new RvAdapter(mData);
rv.setLayoutManager(layoutManager);
rv.setAdapter(adapter);
接下來(lái)才是真正實(shí)現(xiàn)拖動(dòng)和側(cè)滑刪除的時(shí)候呢。用的SDK提供的ItemTouchHelper這個(gè)工具類,它需要一個(gè)CallBack回調(diào)函數(shù),這里我們使用ItemTouchHelper.Callback由于ItemTouchHelper.Callback是一個(gè)抽象函數(shù),所以需要新建一個(gè)類去繼承它。
public class DragItem extends ItemTouchHelper.Callback {
private RvAdapter adapter;
public DragItem(RvAdapter adapter) {
this.adapter = adapter;
}
/**
* 返回滑動(dòng)的方向
* @param recyclerView
* @param viewHolder
* @return
*/
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlag;
int swipeFlag;
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
//允許上下左右的拖動(dòng)
dragFlag = ItemTouchHelper.DOWN
| ItemTouchHelper.UP
| ItemTouchHelper.RIGHT
| ItemTouchHelper.LEFT;
swipeFlag=0;
}else{
dragFlag=ItemTouchHelper.DOWN|ItemTouchHelper.UP;
swipeFlag=ItemTouchHelper.LEFT;//只允許從右到左的側(cè)滑
}
return makeMovementFlags(dragFlag,swipeFlag);
}
/**
* 當(dāng)用戶拖動(dòng)一個(gè)item從舊的位置移動(dòng)到新的位置時(shí)會(huì)調(diào)用此方法
* @param recyclerView
* @param viewHolder
* @param target
* @return
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getAdapterPosition();
int toPosition = target.getAdapterPosition();
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(adapter.getDataList(), i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(adapter.getDataList(), i, i - 1);
}
}
recyclerView.getAdapter().notifyItemMoved(fromPosition, toPosition);
return true;
}
/**
* 當(dāng)用戶左右滑動(dòng)item達(dá)到刪除條件時(shí)會(huì)調(diào)用此方法
* 一般達(dá)到item的一般寬度時(shí)才會(huì)刪除,否則彈回原位置
* @param viewHolder
* @param direction
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
if (direction == ItemTouchHelper.END) {
adapter.getDataList().remove(position);
adapter.notifyItemRemoved(position);
}
adapter.onItemDissmiss(position);
}
/**
* 當(dāng)某個(gè)item由靜止?fàn)顟B(tài)變?yōu)榛瑒?dòng)或拖動(dòng)狀態(tài)時(shí)調(diào)用此方法
* @param viewHolder
* @param actionState
*/
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if(actionState==ItemTouchHelper.ACTION_STATE_DRAG){
viewHolder.itemView.setBackgroundColor(Color.GRAY);
}
}
/**
* 當(dāng)用戶操作完某個(gè)item動(dòng)畫結(jié)束時(shí)調(diào)用此方法
* @param recyclerView
* @param viewHolder
*/
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setBackgroundColor(0);
}
/**
* 是否支持長(zhǎng)按拖動(dòng)
* 默認(rèn)返回true
* @return
*/
@Override
public boolean isLongPressDragEnabled() {
return true;
}
/**
* 是否支持側(cè)滑刪除
* 默認(rèn)返回true
* @return
*/
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
}
各個(gè)方法的含義與調(diào)用時(shí)期在注釋中已經(jīng)說(shuō)得很清楚了,這里就不再重復(fù)了
最后只需要在MainActivity里面新建一個(gè)ItemTouchHelper并把CallBack傳進(jìn)去,再調(diào)用helper的attachToRecyclerView方法綁定recyclerView就可以啦
ItemTouchHelper helper=new ItemTouchHelper(new DragItem(adapter));
helper.attachToRecyclerView(rv);
當(dāng)然卡片式布局也是可以拖動(dòng)的

有圖有真相2.gif
最后附上項(xiàng)目的源代碼地址
https://github.com/HelloNanKe/RecyclerViewSwipeDrag