Android--实现类似支付宝的功能拖拽、增删

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/chaoyu168/article/details/88070362

一、效果图:

二、源码下载

下载地址:https://download.csdn.net/download/chaoyu168/10989276

三、原理

思路分析:

1、导包、在布局中使用RecyclerView

2、需要一个JavaBean用来存储展示信息

3、需要一个填充RecyclerView的布局文件

4、在代码中找到RecyclerView,并为其绑定Adapter和触摸事件

5、适配器的编写、触摸事件的处理

RecycleView实现拖拽交换位置的效果要简单很多,因为通过SDK中的ItemTouchHelper工具类可以轻松的实现这种效果,并且一套代码支持所有布局方式,只需要给recyclerView添加一个ItemTouchHelper对象就行。

mItemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() );
mItemTouchHelper.attachToRecyclerView(mRecyclerView);

构造方法中需要一个CallBack对象,适用于拖拽或者剔除时的回调方法,所以我们主要是要重写CallBack中的相应方法,处理响应的逻辑

首先来自定义一个CallBack类,继承与ItemTouchHepler.Callback()对象

//决定拖拽/滑动的方向
public abstract int getMovementFlags(RecyclerView recyclerView,
        ViewHolder viewHolder);
 
//和位置交换有关,可用于实现drag功能
public abstract boolean onMove(RecyclerView recyclerView,
        ViewHolder viewHolder, ViewHolder target);
 
//和滑动有关,可用于实现swipe功能
public abstract void onSwiped(ViewHolder viewHolder, int direction);
 
//是否长按启用拖拽功能,默认是true
public boolean isLongPressDragEnabled() {return true;}
 
//是否支持滑动,默认true
public boolean isItemViewSwipeEnabled() {return true;}
 
//和目标View的状态改变有关,例如drag,swipe,ide
public void onSelectedChanged(ViewHolder viewHolder, int actionState) {}
 
//和移除View的状态有关,通常用于清除在onSelectedChanged,onChildDraw中对View设置的动画
public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) {}

getMovementFlags() 
用于设置是否处理拖拽事件和滑动事件,以及拖拽和滑动操作的方向,有以下两种情况:

如果是列表类型的,拖拽只有ItemTouchHelper.UP、ItemTouchHelper.DOWN两个方向
如果是网格类型的,拖拽则有UP、DOWN、LEFT、RIGHT四个方向
另外,滑动方向列表类型的,有START和END两个方法,如果是网格类型的一般不设置支持滑动操作可以将swipeFlags = 0置为0,表示不支持滑动操作! 
最后,需要调用return makeMovementFlags(dragFlags, swipeFlags);将设置的标志位return回去!

对应这个方法的代码如下:

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
                if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
                    final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |
                            ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
                    final int swipeFlags = 0;
                    return makeMovementFlags(dragFlags, swipeFlags);
                } else {
                    final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
                    final int swipeFlags = 0;
                    return makeMovementFlags(dragFlags, swipeFlags);
                }
            }

onMove() 
如果我们设置了相关的dragFlags ,那么当我们长按item的时候就会进入拖拽并在拖拽过程中不断回调onMove()方法,我们就在这个方法里获取当前拖拽的item和已经被拖拽到所处位置的item的ViewHolder。

@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    //得到当拖拽的viewHolder的Position
    int fromPosition = viewHolder.getAdapterPosition();
    //拿到当前拖拽到的item的viewHolder
    int toPosition = target.getAdapterPosition();
    if (fromPosition < toPosition) {
        for (int i = fromPosition; i < toPosition; i++) {
            Collections.swap(datas, i, i + 1);
        }
    } else {
        for (int i = fromPosition; i > toPosition; i--) {
            Collections.swap(datas, i, i - 1);
        }
    }
    myAdapter.notifyItemMoved(fromPosition, toPosition);
    return true;
}

onSwipe() 
如果我们设置了相关的swipeFlags,那么当我们滑动item的时候就会调用onSwipe()方法,一般的话在使用LinearLayoutManager的时候,在这个方法里可以删除item,来实现滑动删除!

isLongPressDragEnabled()、isItemViewSwipeEnabled()   

如果我们不重写这两个方法,那么拖拽和滑动都是默认开启的,如果需要我们自定义拖拽和滑动,可以设置为false,然后调用startDrag()startSwipe()方法来开启!

在拖拽的时候将被拖拽的Item高亮,这样用户体验要好很多,所以我们要重写CallBack对象中的onSelectedChanged()和clearView()方法,在选中的时候设置高亮背景色,在完成的时候移除高亮背景色,代码如下:

/**
 * 长按选中Item的时候开始调用
 *
 * @param viewHolder
 * @param actionState
 */
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
    if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
        viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
    }
    super.onSelectedChanged(viewHolder, actionState);
}
 
/**
 * 手指松开的时候还原
 * @param recyclerView
 * @param viewHolder
 */
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    super.clearView(recyclerView, viewHolder);
    viewHolder.itemView.setBackgroundColor(0);
}

这样就实现了我们的基本要求,但是实际功能中有可能存在,排头前两个的不需改变它的顺序,即有些item允许拖拽,有些则不允许,所以我们需要重写isLongPressDragEnabled()设置不允许长按拖拽

/**
 * 重写拖拽不可用
 * @return
 */
@Override
public boolean isLongPressDragEnabled() {
    return false;
}

然后在重写RecycleView的长按监听(这个要自己写个接口去实现),在返回的长按方法中判断是否为不可拖拽的item,若不是,则调用ItemTouchHelper的startDrag()方法,逻辑出入如下:

@Override
 public void onItemLongClick(RecyclerView.ViewHolder vh) {
     //判断被拖拽的是否是前两个,如果不是则执行拖拽
     if (vh.getLayoutPosition() != 0 && vh.getLayoutPosition() != 1) {
         mItemTouchHelper.startDrag(vh);
 
     }
 }

onSelectedChanged() 

这个方法在选中Item的时候(拖拽或者滑动开始的时候)调用,通常这个方法里我们可以改变选中item的背景颜色等,高亮表示选中来提高用户体验。 
需要注意的是,这里的第二个参数int actionState,它有以下3个值,分别表示3种状态:

ACTION_STATE_IDLE:闲置状态
ACTION_STATE_SWIPE:滑动状态
ACTION_STATE_DRAG:拖拽状态
我们可以根据这个状态值,作不同的逻辑处理!

clearView()

这个方法在当手指松开的时候(拖拽或滑动完成的时候)调用,这时候我们可以将item恢复为原来的状态。

最后在代码中:

ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SimpleItemTouchCallback(data, adapter));
itemTouchHelper.attachToRecyclerView(recyclerView);

先得到ItemTouchHelper 实例,构造方法中传入我们自定义的Callback,然后调用attachToRecyclerView(recyclerView),传入需要绑定的RecyclerView即可!

猜你喜欢

转载自blog.csdn.net/chaoyu168/article/details/88070362
今日推荐