学习RecyclerView+ItemTouchHelper实现拖拽和侧滑删除
一、ItemTouchHelper
This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.
专门支持RecyclerView中的Item滑动删除和拖拽移动的效果
所以第一步:继承ItemTouchHelper.Callback重写抽象方法
package com.ahtelit.zbv.simulaterecyclerviewitemhandler;
import android.graphics.Canvas;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
/**
* Created by Administrator on 2018/4/24.
* qzx
*/
public class HandleItemTouchHelperCallback extends ItemTouchHelper.Callback {
ItemTouchHelperAdapter adapter;
public HandleItemTouchHelperCallback(ItemTouchHelperAdapter adapter){
this.adapter=adapter;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//可以拖拽移动
// int dragFlag=ItemTouchHelper.UP|ItemTouchHelper.DOWN|ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT;
int dragFlag=ItemTouchHelper.UP|ItemTouchHelper.DOWN;//只可上下拖拽移动
//可以滑动删除
int swipeFlag=ItemTouchHelper.LEFT;// 只能从右朝左滑动删除
return makeMovementFlags(dragFlag,swipeFlag);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
adapter.onItemMove(viewHolder.getAdapterPosition(),target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
adapter.onItemDismiss(viewHolder.getAdapterPosition());
}
//默认滑动RecyclerView宽度的一半就可以删除
@Override
public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) {
return super.getSwipeThreshold(viewHolder);
}
// private static final int MAX_ICON_WIDTH=20;
// private int fixWidth=5;
// @Override
// public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
// super.clearView(recyclerView, viewHolder);
// //复位
// viewHolder.itemView.setScrollX(0);
// ((RVAdapter.MyRWViewHolder)viewHolder).tv_swipe.setText("左滑删除");
// FrameLayout.LayoutParams layoutParams=(FrameLayout.LayoutParams) ((RVAdapter.MyRWViewHolder)viewHolder).img.getLayoutParams();
// layoutParams.width=5;
// layoutParams.height=5;
// ((RVAdapter.MyRWViewHolder)viewHolder).img.setLayoutParams(layoutParams);
// ((RVAdapter.MyRWViewHolder)viewHolder).img.setVisibility(View.INVISIBLE);
// }
//
// @Override
// public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
//
// //dX表示:用户手指滑动在方向上的距离,向左滑动为负数
// if(actionState==ItemTouchHelper.ACTION_STATE_SWIPE){
//
// if(Math.abs(dX)<getSideWidth(viewHolder)){
// //让其慢慢滑动出来
// viewHolder.itemView.scrollTo(-(int) dX,0);
// }else{
// if(Math.abs(dX)<=recyclerView.getWidth()/2){
// //
// double distance=recyclerView.getWidth()/2-getSideWidth(viewHolder);
// double factor=MAX_ICON_WIDTH/distance;
// double diff=(Math.abs(dX)-getSideWidth(viewHolder))*factor;
// Log.d("zbv","diff="+diff+";dx="+dX);
// if(diff>=MAX_ICON_WIDTH){
// diff=MAX_ICON_WIDTH;
// }
// ((RVAdapter.MyRWViewHolder)viewHolder).tv_swipe.setText(""); //把文字去掉
// ((RVAdapter.MyRWViewHolder) viewHolder).img.setVisibility(View.VISIBLE); //显示眼睛
// FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) ((RVAdapter.MyRWViewHolder) viewHolder).img.getLayoutParams();
// params.width = (int) (fixWidth + diff);
// params.height = (int) (fixWidth + diff);
// ((RVAdapter.MyRWViewHolder) viewHolder).img.setLayoutParams(params);
//
// }
// }
//
// }else{
// super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
// }
//
// }
//
// private int getSideWidth(RecyclerView.ViewHolder viewHolder){
//
// ViewGroup viewGroup=(ViewGroup) viewHolder.itemView;
Log.d("zbv","width_1="+viewGroup.getChildAt(1).getWidth()
+";width_2="+viewGroup.getChildAt(1).getLayoutParams().width);
// return viewGroup.getChildAt(1).getLayoutParams().width;
// }
}
说明一下:我删除的部分主要实现自定义侧滑删除效果借鉴于大神https://blog.csdn.net/a553181867/article/details/54799391的效果
二、定义适配器接口
package com.ahtelit.zbv.simulaterecyclerviewitemhandler;
/**
* Created by Administrator on 2018/4/24.
* qzx
*/
public interface ItemTouchHelperAdapter {
void onItemMove(int fromPosition,int toPosition);
void onItemDismiss(int position);
}
说明:重点是抽出
接口方法实现移动Move和Dismiss
三、RecyclerView的适配器
package com.ahtelit.zbv.simulaterecyclerviewitemhandler;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by Administrator on 2018/4/24.
* qzx
*/
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.MyRWViewHolder> implements ItemTouchHelperAdapter{
private List<String> mDatas;
private Context mContext;
public RVAdapter(Context context, ArrayList<String> list){
mContext=context;
mDatas=list;
}
@Override
public MyRWViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MyRWViewHolder(LayoutInflater.from(mContext).inflate(R.layout.rv_item_layout,parent,false));
}
@Override
public void onBindViewHolder(MyRWViewHolder holder, int position) {
holder.tv.setText(mDatas.get(position));
}
@Override
public int getItemCount() {
return mDatas.size();
}
//public 并且集成rw的ViewHolder
public static class MyRWViewHolder extends RecyclerView.ViewHolder{
public TextView tv;
public ImageView img;
public TextView tv_swipe;
public MyRWViewHolder(View itemView) {
super(itemView);
tv=(TextView)itemView.findViewById(R.id.tv);
img=(ImageView) itemView.findViewById(R.id.swipe_img);
tv_swipe=(TextView) itemView.findViewById(R.id.swipe_tv);
}
}
//实现ItemTouchHelperAdapter接口方法
@Override
public void onItemMove(int fromPosition, int toPosition) {
//交换数据
Collections.swap(mDatas,fromPosition,toPosition);
notifyItemMoved(fromPosition,toPosition);
}
@Override
public void onItemDismiss(int position) {
mDatas.remove(position);
notifyItemRemoved(position);
}
}
申明:我在加载item布局的时候一开始使用:
LayoutInflater.from(mContext).inflate(R.layout.rv_item_layout,null);
出现了Item的布局我明明设置了Match_Parent却还是Content_Wrap的效果
四、主Activity
package com.ahtelit.zbv.simulaterecyclerviewitemhandler;
import android.graphics.Rect;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ItemTouchHelper helper;
private ArrayList<String> list;
private RVAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView=(RecyclerView) findViewById(R.id.recyclerview);
// GridLayoutManager gridLayoutManager=new GridLayoutManager(this,4);
LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
//-------------------------------------ItemDecoration
// DisplayMetrics dm=new DisplayMetrics();
// getWindowManager().getDefaultDisplay().getMetrics(dm);
// final int screenWidth=dm.widthPixels;
// int screenHeight=dm.heightPixels;
// recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
// @Override
// public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
// RecyclerView.LayoutManager layoutManager=parent.getLayoutManager();
// int spanCount=((GridLayoutManager)layoutManager).getSpanCount();
// int itemCount=parent.getAdapter().getItemCount();
// int pos=((GridLayoutManager.LayoutParams)view.getLayoutParams()).getViewLayoutPosition();
if((pos+1)%spanCount==0){
outRect.set(20,20,0,0);
}else{
// outRect.set(20,20,20,20);
}
// }
// });
//----------------------------------------------------------------------------------
list=new ArrayList<String>();
for(int i=0;i<15;i++){
list.add("七子笑"+i);
}
mAdapter=new RVAdapter(this,list);
recyclerView.setAdapter(mAdapter);
//ItemTouchHelper
helper=new ItemTouchHelper(new HandleItemTouchHelperCallback(mAdapter));
helper.attachToRecyclerView(recyclerView);
}
}
五、附上xml
Activity布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.ahtelit.zbv.simulaterecyclerviewitemhandler.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
Item布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<!--
<TextView
android:id="@+id/tv"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="七子笑"
android:background="#ffffff00"
android:gravity="center"
/>
-->
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="七子笑"
/>
<!--
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#ffffff"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="4dp"
app:cardCornerRadius="1dp"
app:elevation="1dp"
app:contentPadding="1dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<TextView
android:id="@+id/item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
android:padding="4dp"
android:layout_centerInParent="true"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
-->
<FrameLayout
android:layout_width="50dp"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/swipe_img"
android:layout_width="5dp"
android:layout_height="5dp"
android:layout_gravity="center"
android:src="@mipmap/ic_launcher"
android:visibility="invisible"
/>
<TextView
android:id="@+id/swipe_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="左滑删除" />
</FrameLayout>
</LinearLayout>
最后在提一嘴:
(1)使用RecyclerView需要在gradle文件中添加:
compile ‘com.android.support:recyclerview-v7:26.1.0’
(2)我布局中使用了CardView同样需要在gradle中添加:
compile ‘com.android.support:cardview-v7:26.1.0’