RecyclerView 使用ItemTouchHelper实现
ItemTouchHelper的核心在于ItemTouchHelper.Callback接口。temTouchHelper.Callback中几个比较重要的方法:
getSwipeThreshold() (返回值表示所能够接受的侧滑滑动的最大距离,当我们侧滑的距离大于该方法的返回值时,就会触发侧滑删除的操作。如果是自定义了删除按钮进行点击来执行删除item操作,因为该返回值表示百分比,那么我们只要把值设置成大于1就可以使得无论侧滑多少都不会触发侧滑删除这个操作了)
getSwipeEscapeVelocity() (侧滑的速度大于该方法的返回值也会触发侧滑删除的操作,如果是自定义删除按钮,设置值同上)
onChildDraw() (该方法在ItemView进行滑动时会回调,这里的滑动包括:1、手指滑动;2、ItemView的位移动画。可以根据isCurrentlyActive参数来判断是手指滑动还是动画滑动)
clearView() (该方法在ItemView滑动完成之后会回调,想要实现侧滑ItemView停在某种状态,判断手指松开时ItemView的滑动距离是否大于我们设置的阈值(是否显示删除按钮的阈值),如果大于的话,只滑动到指定的位置,如果小于的话,就回到初始位置)
具体实现:
1、创建一个Activity,RecyclerActivity.java:
//import android.graphics.Canvas;
import android.os.Bundle;
import android.view.View;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
//import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class RecyclerActivity extends FatherActivity{
private String[] titles = {"china","america","apple","canada","water","flower","candy","lisa","jon","teacher","student","moon","second","dog"};
private String[] contents = {"This is china","This is america","This is apple","This is canada","This is water","This is water","This is water","This is water","This is water","This is water","This is water","This is water","This is water","This is water"};
private int[] leftImages = {R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher,R.mipmap.ic_launcher};
List<RecyclerModel> list;//数据源
RecyclerView recyclerView;
CustomRecyclerViewAdapter customRecyclerViewAdapter;
// RecyclerModel recyclerModel;//保存正在拖动的item所对应的对象
// String dragStartTag;//记录recyclerview拖动item的起始位置
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler);
initView();
}
void initView(){
//加载数据
list = new ArrayList<>();
for(int i = 0; i < titles.length; i++){
RecyclerModel model = new RecyclerModel(leftImages[i],titles[i],contents[i]);
list.add(model);
}
customRecyclerViewAdapter = new CustomRecyclerViewAdapter(list);
recyclerView = findViewById(R.id.recycler_recyclerview);
//设置adapter
recyclerView.setAdapter(customRecyclerViewAdapter);
//加载LayoutManager
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
//初始化ItemTouchHelper
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new CustomItemTouchHelperCallback(GeneralFunction.dpToPx(this, 60),list));
itemTouchHelper.attachToRecyclerView(recyclerView);
// //拖动起始记录值与拖动的item暂存对象初始值为空
// recyclerModel = null;
// dragStartTag = null;
// ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
// //itemView可滑动的最大阈值(当滑动距离超过最大阈值,松开手指时会回弹到阈值的位置)
// int mDefaultScrollX = GeneralFunction.dpToPx(RecyclerActivity.this,64);
// /**
// *这个方法用于让RecyclerView拦截上下滑动和左右滑动的事件
// * makeMovementFlags(dragFlags, swipeFlags);dragFlags是上下方向的滑动 swipeFlags是左右方向上的滑动
// */
// @Override
// public int getMovementFlags(@NotNull RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder viewHolder) {
// return makeMovementFlags(ItemTouchHelper.UP|ItemTouchHelper.DOWN,ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT);
// }
//
// /**
// * 针对drag状态,在canDropOver()返回true时,会调用该方法
// * 这里需要我们自己处理拖动后互换位置的逻辑
// */
// @Override
// public boolean onMove(@NotNull RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder viewHolder, @NotNull RecyclerView.ViewHolder target) {
// if(recyclerView.getAdapter() != null){//拖动过程中不断更换位置
// recyclerView.getAdapter().notifyItemMoved(viewHolder.getAdapterPosition(),target.getAdapterPosition());
// }
// return true;
// }
//
// /**
// * 针对drag状态,当前target对应的item是否允许移动
// * 我们一般用drag来做一些换位置的操作,就是当前对应的target对应的Item可以移动
// */
// @Override
// public boolean canDropOver(@NotNull RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder current, @NotNull RecyclerView.ViewHolder target) {
// return true;
// }
//
// /**
// * 针对drag状态,当drag ItemView跟底下ItemView重叠时,可以给drag ItemView设置一个Margin值
// * 让重叠不容易发生,相当于增大了drag Item的区域
// */
// @Override
// public int getBoundingBoxMargin() {
// return 0;
// }
//
// /**
// * 针对drag状态,当滑动超过多少就可以出发onMove()方法(这里指onMove()方法的调用,并不是随手指移动的View)
// */
// public float getMoveThreshold(@NotNull RecyclerView.ViewHolder viewHolder) {
// return .5f;
// }
//
// /**
// * 针对drag状态,在drag的过程中获取drag itemView底下对应的ViewHolder(一般不用我们处理直接super就好了)
// */
// public RecyclerView.ViewHolder chooseDropTarget(@NotNull RecyclerView.ViewHolder selected,
// @NotNull List<RecyclerView.ViewHolder> dropTargets,
// int curX,
// int curY) {
// return super.chooseDropTarget(selected, dropTargets, curX, curY);
// }
//
// /**
// * 当onMove return true的时候调用(一般不用我们自己处理,直接super就好)
// */
// public void onMoved(@NotNull final RecyclerView recyclerView,
// @NotNull final RecyclerView.ViewHolder viewHolder,
// int fromPos,
// @NotNull final RecyclerView.ViewHolder target,
// int toPos,
// int x,
// int y) {
// super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y);
// }
//
// /**
// * 针对swipe和drag状态,当一个item view在swipe、drag状态结束的时候调用
// * drag状态:当手指释放的时候会调用
// * swipe状态:当item从RecyclerView中删除的时候调用,一般我们会在onSwiped()函数里面删除掉指定的item view
// */
// public void clearView(@NotNull RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder viewHolder) {
// super.clearView(recyclerView, viewHolder);
//
// if (recyclerView.getAdapter()!=null){
// //dragStartTag和recyclerModel都不为空则是drag状态
// if (dragStartTag!=null && recyclerModel!=null){
// viewHolder.itemView.setBackgroundColor(getResources().getColor(R.color.colorSelect));//item样式恢复原样
// int endLocation = viewHolder.getAdapterPosition();//获取正在拖动的item对象的最终目标位置
// int start = Integer.parseInt(dragStartTag);//获取已记录的item起始位置
// list.remove(start);//先删除数组里相对应的正在拖动的item对象
// list.add(endLocation,recyclerModel);//在数组对应的最终目标位置插入先前保存的item对象
// if (start>endLocation){
// //起始位置大于目标位置,那么recyclerView局部刷新范围则是,从目标位置开始到起始位置结束范围内刷新数据
// recyclerView.getAdapter().notifyItemRangeChanged(endLocation,start-endLocation+1);
// }else if (start<endLocation){
// //起始位置小于目标位置,那么recyclerView局部刷新范围则是,从起始位置开始到目标位置结束范围内刷新数据
// recyclerView.getAdapter().notifyItemRangeChanged(start,endLocation-start+1);
// }
// //拖动结束最后要将记录值与暂存的item对象置为空
// dragStartTag = null;
// recyclerModel = null;
//
// }
//// else {//swipe状态
//// if (viewHolder.itemView.getScrollX() >= mDefaultScrollX) {
//// viewHolder.itemView.scrollTo(mDefaultScrollX, 0);//让item最终偏移量为阈值即可显示删除按钮
//// } else {
//// //往右滑的时候直接恢复初始位置(此时getScrollX()永远小于阈值,因为往右滑偏移量是负值)
//// viewHolder.itemView.scrollTo(0, 0);
//// }
//// }
// }
//
// }
//
// /**
// * 针对swipe和drag状态,整个过程中一直会调用这个函数,随手指移动的view就是在super里面做到的(和ItemDecoration里面的onDraw()函数对应)
// */
// public void onChildDraw(@NotNull Canvas c, @NotNull RecyclerView recyclerView, @NotNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
// super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
//
// //当处于Swipe状态时
// if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){
// //dX的值,表示手指滑动的距离,往右滑动为正,往左为负
// // getScrollX()的值,表示itemView的偏移量,往右是负,往左是正
// if (isCurrentlyActive) {//手指滑动时
// // 基于当前位置的偏移
// viewHolder.itemView.scrollTo( (int)-dX, 0);
// } else {//手指松开时,因为我们设置了侧滑距离无论多大也不会删除item,所以手指松开时,itemView会回滚
// //判断ItemView的偏移量是否大于给定阈值,如果大于让itemView的偏移量最终停留在阈值,显示删除按钮
// if (viewHolder.itemView.getScrollX() >= mDefaultScrollX) {
// viewHolder.itemView.scrollTo(mDefaultScrollX, 0);//让item最终偏移量为阈值即可显示删除按钮
// } else {
// //往右滑的时候直接恢复初始位置(此时getScrollX()永远小于阈值,因为往右滑偏移量是负值)
// viewHolder.itemView.scrollTo(0, 0);
// }
// }
// }
//
// }
//
// /**
// * 针对swipe和drag状态,整个过程中一直会调用这个函数(和ItemDecoration里面的onDrawOver()函数对应)
// * 这个函数提供给我们可以在RecyclerView的上面再绘制一层东西,比如绘制一层蒙层啥的
// */
// public void onChildDrawOver(@NotNull Canvas c, @NotNull RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
// super.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
// }
//
// /**
// * 针对swipe和drag状态,当手指离开之后,view回到指定位置动画的持续时间(swipe可能是回到原位,也有可能是swipe掉)
// */
// public long getAnimationDuration(@NotNull RecyclerView recyclerView, int animationType, float animateDx, float animateDy) {
// return super.getAnimationDuration(recyclerView, animationType, animateDx, animateDy);
// }
//
// /**
// * 针对drag状态,当itemView滑动到RecyclerView边界的时候(比如下面边界的时候),RecyclerView会scroll,
// * 同时会调用该函数去获取scroller距离(不用我们处理 直接super)
// */
// public int interpolateOutOfBoundsScroll(@NotNull RecyclerView recyclerView,
// int viewSize,
// int viewSizeOutOfBounds,
// int totalSize,
// long msSinceStartScroll) {
// return super.interpolateOutOfBoundsScroll(recyclerView, viewSize, viewSizeOutOfBounds, totalSize, msSinceStartScroll);
// }
//
// /**
// * 针对swipe和drag状态,当swipe或者drag对应的ViewHolder改变的时候调用
// * 我们可以通过重写这个函数获取到swipe、drag开始和结束时机,viewHolder 不为空的时候是开始,空的时候是结束
// * 即处于拖动或者滑动时调用
// */
// public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
// super.onSelectedChanged(viewHolder, actionState);
// //当item开始拖动时,需要处理的逻辑
// if(actionState == ItemTouchHelper.ACTION_STATE_DRAG && viewHolder!=null){
// viewHolder.itemView.setBackgroundColor(getResources().getColor(R.color.colorModel));//设置item拖动时样式
// int startLocation = viewHolder.getAdapterPosition();//获取正在拖动的item的起始位置
// dragStartTag = String.valueOf(startLocation);//记录起始位置
// recyclerModel = list.get(startLocation);//将正在拖动的item对象取出暂时保存
// }
// }
//
// /**
// * 针对swipe状态,是否允许swipe(滑动)操作
// */
// public boolean isItemViewSwipeEnabled() {
// return true;
// }
//
// /**
// * 针对swipe状态,swipe滑动的位置超过了百分之多少就消失
// */
// public float getSwipeThreshold(@NotNull RecyclerView.ViewHolder viewHolder) {
// return Integer.MAX_VALUE;//设置成足够大的值,就可以达到滑动到item不可见也不会消失的效果
// }
//
// /**
// * 针对swipe状态,swipe的逃逸速度,换句话说就算没达到getSwipeThreshold设置的距离,达到了这个逃逸速度item也会被swipe消失掉
// */
// public float getSwipeEscapeVelocity(float defaultValue) {
// return Integer.MAX_VALUE;//设置成足够大的值,就可以使得无论逃逸速度有多快也不会消失的效果
// }
//
// /**
// * 针对swipe状态,swipe滑动的阻尼系数,设置最大滑动速度
// */
// public float getSwipeVelocityThreshold(float defaultValue) {
// return defaultValue;
// }
//
// /**
// * 针对swipe状态,swipe 到达滑动消失的距离回调函数,一般在这个函数里面处理删除item的逻辑
// * 确切的来讲是swipe item滑出屏幕动画结束的时候调用
// */
// public void onSwiped(@NotNull RecyclerView.ViewHolder viewHolder, int direction) { }
//
// });
// helper.attachToRecyclerView(recyclerView);
}
public void recycler_backClick(View view){
finish();
}
}
2、Activity的布局文件,activity_recycler.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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=".RecyclerActivity">
<ImageView
android:id="@+id/recycler_actionBar_bg"
android:layout_width="match_parent"
android:layout_height="64dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:background="@color/colorModel"/>
<ImageView
android:id="@+id/recycler_back_bt"
android:layout_width="25dp"
android:layout_height="25dp"
app:layout_constraintBottom_toBottomOf="@+id/recycler_actionBar_bg"
app:layout_constraintLeft_toLeftOf="@+id/recycler_actionBar_bg"
android:layout_marginLeft="5dp"
android:layout_marginBottom="7dp"
android:padding="3dp"
android:src="@mipmap/back"
android:onClick="recycler_backClick"/>
<TextView
android:id="@+id/recycler_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="@+id/recycler_actionBar_bg"
app:layout_constraintBottom_toBottomOf="@+id/recycler_actionBar_bg"
app:layout_constraintRight_toRightOf="@+id/recycler_actionBar_bg"
android:layout_marginBottom="5dp"
android:text="@string/RecyclerActivity_title"
android:textColor="@color/colorWhite"
android:textSize="12pt"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_recyclerview"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@+id/recycler_actionBar_bg"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginTop="50dp"
android:layout_marginLeft="45dp"
android:layout_marginRight="45dp"
android:layout_marginBottom="50dp"
android:background="@color/colorWhite"/>
</androidx.constraintlayout.widget.ConstraintLayout>
3、创建一个对象模型类,RecyclerModel.java:
class RecyclerModel {
int leftImage;
String title;
String content;
RecyclerModel(int leftImage,String title,String content){
this.leftImage = leftImage;
this.title = title;
this.content = content;
}
}
4、创建RecyclerView的item布局,recyclerview_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorSelect"
android:layout_marginTop="1dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/recycler_item_leftImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_margin="5dp"/>
<TextView
android:id="@+id/recycler_item_title"
android:layout_width="0dp"
android:layout_height="22dp"
app:layout_constraintLeft_toRightOf="@+id/recycler_item_leftImage"
app:layout_constraintTop_toTopOf="@+id/recycler_item_leftImage"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="5dp"
android:textColor="@color/colorWhite"/>
<TextView
android:id="@+id/recycler_item_content"
android:layout_width="0dp"
android:layout_height="22dp"
app:layout_constraintLeft_toRightOf="@+id/recycler_item_leftImage"
app:layout_constraintBottom_toBottomOf="@+id/recycler_item_leftImage"
app:layout_constraintRight_toRightOf="parent"
android:textColor="@color/colorWhite"/>
<TextView
android:id="@+id/recycler_item_delete"
android:layout_width="64dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="@+id/recycler_item_title"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="@string/Delete"
android:gravity="center"
android:background="@color/colorRed"/>
</androidx.constraintlayout.widget.ConstraintLayout>
5、创建Adapter,CustomRecyclerViewAdapter.java:
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class CustomRecyclerViewAdapter extends RecyclerView.Adapter<CustomRecyclerViewAdapter.CustomViewHolder>{
private List<RecyclerModel> list;
CustomRecyclerViewAdapter(List<RecyclerModel> list){
this.list = list;
}
@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item,parent,false);
return new CustomViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
RecyclerModel model = list.get(position);
holder.leftImageView.setImageResource(model.leftImage);
holder.titleTextView.setText(model.title);
holder.contentTextView.setText(model.content);
//删除按钮点击事件处理
holder.deleteTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
list.remove(holder.getAdapterPosition());
notifyItemRemoved(holder.getAdapterPosition());//更新数据
holder.itemView.setScrollX(0);//最后要将偏移量归零,防止复用产生的问题
}
});
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.v("position","--------"+holder.getAdapterPosition());
}
});
}
@Override
public int getItemCount() {
return list.size();
}
static class CustomViewHolder extends RecyclerView.ViewHolder{
private ImageView leftImageView;
private TextView titleTextView;
private TextView contentTextView;
private TextView deleteTextView;
CustomViewHolder(@NonNull View itemView) {
super(itemView);
leftImageView = itemView.findViewById(R.id.recycler_item_leftImage);
titleTextView = itemView.findViewById(R.id.recycler_item_title);
contentTextView = itemView.findViewById(R.id.recycler_item_content);
deleteTextView = itemView.findViewById(R.id.recycler_item_delete);
}
}
}
6、创建一个继承自ItemTouchHelper.Callback的类,CustomItemTouchHelperCallback.java:
import android.graphics.Canvas;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class CustomItemTouchHelperCallback extends ItemTouchHelper.Callback {
private final int mDefaultScrollX;//itemView可滑动的最大阈值(当滑动距离超过最大阈值,松开手指时会回弹到阈值的位置)
//拖动起始记录值与拖动的item暂存对象初始值要置为空
private RecyclerModel recyclerModel = null;
private String dragStartTag = null;
//传入的数据源
private final List<RecyclerModel> list;
//CustomItemTouchHelperCallback构造方法,传入默认的最大偏移量和数据源
CustomItemTouchHelperCallback(int defaultScrollX,List<RecyclerModel> list) {
mDefaultScrollX = defaultScrollX;
this.list = list;
}
/**
*这个方法用于让RecyclerView拦截上下滑动和左右滑动的事件
* makeMovementFlags(dragFlags, swipeFlags);dragFlags是上下方向的滑动 swipeFlags是左右方向上的滑动
*/
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
// 上下拖动
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
// 向左滑动
int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlags, swipeFlags);
}
/**
* 针对drag状态,在canDropOver()返回true时,会调用该方法
* 这里需要我们自己处理拖动后互换位置的逻辑
*/
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
if(recyclerView.getAdapter() != null){//拖动过程中不断更换位置
recyclerView.getAdapter().notifyItemMoved(viewHolder.getAdapterPosition(),target.getAdapterPosition());
}
return true;
}
/**
* 针对swipe和drag状态,当一个item view在swipe、drag状态结束的时候调用
* drag状态:当手指释放的时候会调用
* swipe状态:当item从RecyclerView中删除的时候调用,一般我们会在onSwiped()函数里面删除掉指定的item view
*/
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
if (recyclerView.getAdapter()!=null){
//dragStartTag和recyclerModel都不为空则是drag状态
if (dragStartTag!=null && recyclerModel!=null){
viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getResources().getColor(R.color.colorSelect));//item样式恢复原样
int endLocation = viewHolder.getAdapterPosition();//获取正在拖动的item对象的最终目标位置
int start = Integer.parseInt(dragStartTag);//获取已记录的item起始位置
list.remove(start);//先删除数组里相对应的正在拖动的item对象
list.add(endLocation,recyclerModel);//在数组对应的最终目标位置插入先前保存的item对象
if (start>endLocation){
//起始位置大于目标位置,那么recyclerView局部刷新范围则是,从目标位置开始到起始位置结束范围内刷新数据
recyclerView.getAdapter().notifyItemRangeChanged(endLocation,start-endLocation+1);
}else if (start<endLocation){
//起始位置小于目标位置,那么recyclerView局部刷新范围则是,从起始位置开始到目标位置结束范围内刷新数据
recyclerView.getAdapter().notifyItemRangeChanged(start,endLocation-start+1);
}
//拖动结束最后要将记录值与暂存的item对象置为空
dragStartTag = null;
recyclerModel = null;
}
// else {//swipe状态
// if (viewHolder.itemView.getScrollX() >= mDefaultScrollX) {
// viewHolder.itemView.scrollTo(mDefaultScrollX, 0);//让item最终偏移量为阈值即可显示删除按钮
// } else {
// //往右滑的时候直接恢复初始位置(此时getScrollX()永远小于阈值,因为往右滑偏移量是负值)
// viewHolder.itemView.scrollTo(0, 0);
// }
// }
}
}
/**
* 针对swipe和drag状态,整个过程中一直会调用这个函数,随手指移动的view就是在super里面做到的(和ItemDecoration里面的onDraw()函数对应)
*/
@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
//dX的值,表示手指滑动的距离,往右滑动为正,往左为负
// getScrollX()的值,表示itemView的偏移量,往右是负,往左是正
if (isCurrentlyActive) {//手指滑动时
// 基于当前位置的偏移
viewHolder.itemView.scrollTo( (int)-dX, 0);
} else {//手指松开时,因为我们设置了侧滑距离无论多大也不会删除item,所以手指松开时,itemView会回滚
//判断ItemView的偏移量是否大于给定阈值,如果大于让itemView的偏移量最终停留在阈值,显示删除按钮
if (viewHolder.itemView.getScrollX() >= mDefaultScrollX) {
viewHolder.itemView.scrollTo(mDefaultScrollX, 0);//让item最终偏移量为阈值即可显示删除按钮
} else {
//往右滑的时候直接恢复初始位置(此时getScrollX()永远小于阈值,因为往右滑偏移量是负值)
viewHolder.itemView.scrollTo(0, 0);
}
}
}
/**
* 针对swipe和drag状态,当swipe或者drag对应的ViewHolder改变的时候调用
* 我们可以通过重写这个函数获取到swipe、drag开始和结束时机,viewHolder 不为空的时候是开始,空的时候是结束
* 即处于拖动或者滑动时调用
*/
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
//当item开始拖动时,需要处理的逻辑
if(actionState == ItemTouchHelper.ACTION_STATE_DRAG && viewHolder!=null){
//先将拖动起始记录值与拖动的item暂存对象初始值置为空
dragStartTag = null;
recyclerModel = null;
viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getResources().getColor(R.color.colorModel));//设置item拖动时样式
int startLocation = viewHolder.getAdapterPosition();//获取正在拖动的item的起始位置
dragStartTag = String.valueOf(startLocation);//记录起始位置
recyclerModel = list.get(startLocation);//将正在拖动的item对象取出暂时保存
}
}
/**
* 针对swipe状态,swipe滑动的位置超过了百分之多少就消失
*/
@Override
public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
return Integer.MAX_VALUE;
}
/**
* 针对swipe状态,swipe的逃逸速度,换句话说就算没达到getSwipeThreshold设置的距离,达到了这个逃逸速度item也会被swipe消失掉
*/
@Override
public float getSwipeEscapeVelocity(float defaultValue) {
return Integer.MAX_VALUE;//设置成足够大的值,就可以使得无论逃逸速度有多快也不会消失的效果
}
/**
* 针对swipe状态,swipe 到达滑动消失的距离回调函数,一般在这个函数里面处理删除item的逻辑
* 确切的来讲是swipe item滑出屏幕动画结束的时候调用
*/
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { }
}