RecyclerView的中级进阶 侧滑删除和拖拽排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/q714093365/article/details/74533607

RecyclerView相信大家都已经了解,以前我们使用的listView,gradView渐渐的使用的人越来越少.可以说RecyclerView肯定会取代listView,gradView.今天我们来讲讲recyclerview的侧滑删除和拖拽排序.不了解RecyclerView的请自行去百度

在很多时候我们需要使用这样的功能,如果自己用代码去实现拖动排序与滑动删除会比较麻烦还好谷歌为我们提供了一个工具类ItemTouchHelper

官方的解释是它是一个可以给RecyclerView提供添加拖动排序与滑动删除等等操作的工具类。

简单实现

第一步 首先我们创建一个接口ItemTouchHelperAdapter

public interface ItemTouchHelperAdapter {

    //数据交换
    void onItemMove(int fromPosition, int toPosition);

    //数据删除
    void onItemDissmiss(int position);

}
第二步创建一个类SimpleItemTouchHelperCallback继承自ItemTouchHelper.Callback

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
private ItemTouchHelperAdapter mAdapter;

//限制ImageView长度所能增加的最大值
private double ICON_MAX_SIZE = 50;
//ImageView的初始长宽
private int fixedWidth = 150;


public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
    mAdapter = adapter;
}

/**
 * 该方法用于返回可以滑动的方向,比如说允许从右到左侧滑,允许上下拖动等。我们一般使用makeMovementFlags(int,int)或makeFlag(int, int)来构造我们的返回值。
 * 例如:要使RecyclerView的Item可以上下拖动,同时允许从右到左侧滑,但不许允许从左到右的侧滑,我们可以这样写:
 *
 * @param recyclerView
 * @param viewHolder
 * @return
 */
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允许上下的拖动
    int swipeFlags = ItemTouchHelper.LEFT; //只允许从右向左侧滑
    return makeMovementFlags(dragFlags, swipeFlags);
    //  return 0;
}

/**
 * 当用户拖动一个Item进行上下移动从旧的位置到新的位置的时候会调用该方法,在该方法内,我们可以调用Adapter的notifyItemMoved方法来交换两个ViewHolder的位置,
 * 最后返回true,表示被拖动的ViewHolder已经移动到了目的位置。所以,如果要实现拖动交换位置,可以重写该方法(前提是支持上下拖动):
 *
 * @param recyclerView
 * @param viewHolder
 * @param target
 * @return
 */
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    //onItemMove是接口方法
    mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
    return true;
    //  return false;
}

/**
 * 当用户左右滑动Item达到删除条件时,会调用该方法,一般手指触摸滑动的距离达到RecyclerView宽度的一半时,再松开手指,
 * 此时该Item会继续向原先滑动方向滑过去并且调用onSwiped方法进行删除,否则会反向滑回原来的位置。在该方法内部我们可以这样写:
 *
 * @param viewHolder
 * @param direction
 */
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    //onItemDissmiss是接口方法
    mAdapter.onItemDissmiss(viewHolder.getAdapterPosition());
}

/**
 * 该方法返回true时,表示支持长按拖动,即长按ItemView后才可以拖动,我们遇到的场景一般也是这样的。默认是返回true。
 *
 * @return
 */
@Override
public boolean isLongPressDragEnabled() {
    return true;
}

/**
 * 该方法返回true时,表示如果用户触摸并左右滑动了View,那么可以执行滑动删除操作,即可以调用到onSwiped()方法。默认是返回true。
 *
 * @return
 */
@Override
public boolean isItemViewSwipeEnabled() {
    return true;
}

/**
 * 从静止状态变为拖拽或者滑动的时候会回调该方法,参数actionState表示当前的状态。
 *
 * @param viewHolder
 * @param actionState
 */
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
    super.onSelectedChanged(viewHolder, actionState);
}

/**
 * 当用户操作完毕某个item并且其动画也结束后会调用该方法,一般我们在该方法内恢复ItemView的初始状态,防止由于复用而产生的显示错乱问题。
 *
 * @param recyclerView
 * @param viewHolder
 */
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
  //  super.clearView(recyclerView, viewHolder);
    //重置改变,防止由于复用而导致的显示问题
    viewHolder.itemView.setScrollX(0);

    ((FormatListDialogAdapter.ViewHolder) viewHolder).tv_text.setText("左滑删除");
}

/**
 * 我们可以在这个方法内实现我们自定义的交互规则或者自定义的动画效果。
 *
 * @param c
 * @param recyclerView
 * @param viewHolder
 * @param dX
 * @param dY
 * @param actionState
 * @param isCurrentlyActive
 */
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
  //  super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);

    //仅对侧滑状态下的效果做出改变
    if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
        //如果dX小于等于删除方块的宽度,那么我们把该方块滑出来
        if (Math.abs(dX) <= getSlideLimitation(viewHolder)) {
            viewHolder.itemView.scrollTo(-(int) dX, 0);
        }
        //如果dX还未达到能删除的距离,此时慢慢增加“眼睛”的大小,增加的最大值为ICON_MAX_SIZE
        else if (Math.abs(dX) <= recyclerView.getWidth() / 2) {
            double distance = (recyclerView.getWidth() / 2 - getSlideLimitation(viewHolder));
            double factor = ICON_MAX_SIZE / distance;
            double diff = (Math.abs(dX) - getSlideLimitation(viewHolder)) * factor;
            if (diff >= ICON_MAX_SIZE)
                diff = ICON_MAX_SIZE;
            ((FormatListDialogAdapter.ViewHolder) viewHolder).tv_text.setText("松开删除");   //把文字去掉

        }
    } else {
        //拖拽状态下不做改变,需要调用父类的方法
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
}


/**
 * 获取删除方块的宽度
 */
public int getSlideLimitation(RecyclerView.ViewHolder viewHolder) {
    ViewGroup viewGroup = (ViewGroup) viewHolder.itemView;
    return viewGroup.getChildAt(1).getLayoutParams().width;
}
}

第三步RecyclerView的适配器实现ItemTouchHelperAdapter接口

    /**
 * 交换位置
 *
 * @param fromPosition
 * @param toPosition
 */
@Override
public void onItemMove(int fromPosition, int toPosition) {
    //交换位置
    Collections.swap(mCertificateList, fromPosition, toPosition);
    notifyItemMoved(fromPosition, toPosition);
}

/**
 * 移除数据
 *
 * @param position
 */
@Override
public void onItemDissmiss(int position) {

    //获取到证书别名
    if (mCertificateList!=null&&mCertificateList.size()>=0){
        String alias = mCertificateList.get(position).getName();
        //删除证书
        Config.getInstance().getProject().deleteCertificate(alias);
        //移除数据
        mCertificateList.remove(position);
        notifyItemRemoved(position);
    }
}

第四步实现RecyclerView与ItemTouchHelper的关联

//先实例化Callback
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(formatListDialogAdapter);
//用Callback构造ItemtouchHelper
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
//调用ItemTouchHelper的attachToRecyclerView方法建立联系
touchHelper.attachToRecyclerView(certificateListRecyclerView);

到此已经实现了recyclerView的侧滑删除和拖拽排序.在onChildDraw方法中请自行修改动画效果

猜你喜欢

转载自blog.csdn.net/q714093365/article/details/74533607
今日推荐