ItemTouchHelper基本使用方法
step.1新建一个接口,让Adapter实现之
从解耦的角度考虑,我们需要一个接口来实现Adapter和ItemTouchHelper之间涉及数据的操作,因为ItemTouchHelper在完成触摸的各种动画后,就要对Adapter的数据进行操作,比如侧滑删除操作,最后需要调用Adapter的notifyItemRemove()方法来移除该数据。因此我们可以把数据操作的部分抽象成一个接口方法,让ItemTouchHelper.Callback调用该方法即可。具体如下:
一.新建ItemTouchHelperAdapter:
package com.example.deleterecyclerview;
import androidx.recyclerview.widget.RecyclerView;
public interface ItemTouchHelperAdapter {
//交换数据
void onItemMove(int fromPosition,int toPosition);
//删除数据
void onItemDelete(int position);
void onItemSelected(RecyclerView.ViewHolder viewHolder);
void onItemSelectedEnd(RecyclerView.ViewHolder viewHolder);
}
二.让recyclerview的adapter实现这个接口
package com.example.deleterecyclerview;
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.Collection;
import java.util.Collections;
import java.util.List;
public class TabAdapter extends RecyclerView.Adapter<TabAdapter.ViewHolder> implements ItemTouchHelperAdapter {
private List<TabInfo> mTabInfoList;
public List<TabInfo> getTabInfoList() {
return mTabInfoList;
}
public void setTabInfoList(List<TabInfo> mTabInfoList) {
this.mTabInfoList = mTabInfoList;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.tab_item_layout, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
TabInfo tabInfo = mTabInfoList.get(position);
holder.tabImage.setImageResource(tabInfo.getTabImage());
holder.tabText.setText(tabInfo.getTabText());
holder.tabItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
@Override
public int getItemCount() {
return mTabInfoList.size();
}
@Override
public void onItemMove(int fromPosition, int toPosition) {
Collections.swap(mTabInfoList, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onItemDelete(int position) {
mTabInfoList.remove(position);
notifyItemRemoved(position);
}
@Override
public void onItemSelected(RecyclerView.ViewHolder viewHolder) {
viewHolder.itemView.setScaleX(1.2f);
viewHolder.itemView.setScaleY(1.2f);
}
@Override
public void onItemSelectedEnd(RecyclerView.ViewHolder viewHolder) {
Log.d("lhm", "onItemSelectedEnd: 1111");
viewHolder.itemView.setScaleX(1.0f);
viewHolder.itemView.setScaleY(1.0f);
}
protected class ViewHolder extends RecyclerView.ViewHolder {
private TextView tabText;
private ImageView tabImage;
private ViewGroup tabItem;
public ViewHolder(@NonNull View itemView) {
super(itemView);
this.tabText = itemView.findViewById(R.id.tab_text);
this.tabImage = itemView.findViewById(R.id.tab_image);
this.tabItem = (ViewGroup) itemView;
}
}
}
三.新建类继承自ItemTouchHelper.Callback
从官方文档我们知道,使用ItemTouchHelper需要一个Callback,该Callback是ItemTouchHelper.Callback的子类,所以我们需要新建一个类比如SimpleItemTouchHelperCallback继承自ItemTouchHelper.Callback。我们可以重写其数个方法来实现我们的需求。我们先来看看ItemTouchHelper.Callback需要重写的几个常用的方法。
1、public int getMovementFlags(RecyclerView, RecyclerView.ViewHolder):
该方法用于返回可以滑动的方向,比如说允许从右到左侧滑,允许上下拖动等。我们一般使用makeMovementFlags(int,int)或makeFlag(int, int)来构造我们的返回值。
例如:要使RecyclerView的Item可以上下拖动,同时允许从右到左侧滑,但不许允许从左到右的侧滑,我们可以这样写:
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允许上下的拖动
int swipeFlags = ItemTouchHelper.LEFT; //只允许从右向左侧滑
return makeMovementFlags(dragFlags,swipeFlags);
}
2、public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)
当用户拖动一个Item进行上下移动从旧的位置到新的位置的时候会调用该方法,在该方法内,我们可以调用Adapter的notifyItemMoved方法来交换两个ViewHolder的位置,最后返回true,表示被拖动的ViewHolder已经移动到了目的位置。所以,如果要实现拖动交换位置,可以重写该方法(前提是支持上下拖动):
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
mItemTouchHelperAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
3、public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)
当用户左右滑动Item达到删除条件时,会调用该方法,一般手指触摸滑动的距离达到RecyclerView宽度的一半时,再松开手指,此时该Item会继续向原先滑动方向滑过去并且调用onSwiped方法进行删除,否则会反向滑回原来的位置。在该方法内部我们可以这样写:
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
mItemTouchHelperAdapter.onItemDelete(viewHolder.getAdapterPosition());
}
4、public boolean isLongPressDragEnabled():该方法返回true时,表示支持长按拖动,即长按ItemView后才可以拖动,我们遇到的场景一般也是这样的。默认是返回true。
5、public boolean boolean isItemViewSwipeEnabled():该方法返回true时,表示如果用户触摸并左右滑动了View,那么可以执行滑动删除操作,即可以调用到onSwiped()方法。默认是返回true。
6、public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState):从静止状态变为拖拽或者滑动的时候会回调该方法,参数actionState表示当前的状态。
7、public void clearView(RecyclerView recyclerView, ViewHolder viewHolder):当用户操作完毕某个item并且其动画也结束后会调用该方法,一般我们在该方法内恢复ItemView的初始状态,防止由于复用而产生的显示错乱问题。
8、public void onChildDraw(…):我们可以在这个方法内实现我们自定义的交互规则或者自定义的动画效果。
那么完整的SimpleItemTouchHelperCallback文件是这样的:
package com.example.deleterecyclerview;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
private ItemTouchHelperAdapter mItemTouchHelperAdapter;
public void setItemTouchHelperAdapter(ItemTouchHelperAdapter itemTouchHelperAdapter) {
this.mItemTouchHelperAdapter = itemTouchHelperAdapter;
}
public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter mItemTouchHelperAdapter) {
this.mItemTouchHelperAdapter = mItemTouchHelperAdapter;
}
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN|ItemTouchHelper.RIGHT|ItemTouchHelper.LEFT;
int swiperFlags = ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlags, swiperFlags);
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
mItemTouchHelperAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
mItemTouchHelperAdapter.onItemDelete(viewHolder.getAdapterPosition());
}
@Override
public boolean isLongPressDragEnabled() {
return true;
}
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
@Override
public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if(actionState!=ItemTouchHelper.ACTION_STATE_IDLE){
mItemTouchHelperAdapter.onItemSelected(viewHolder);
}
}
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
if(!recyclerView.isComputingLayout()){
mItemTouchHelperAdapter.onItemSelectedEnd(viewHolder);
}
}
}
四,为RecyclerView添加ItemTouchHelper
ItemTouchHelper.Callback callback=new SimpleItemTouchHelperCallback(mTabAdapter);
ItemTouchHelper itemTouchHelper=new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);