RecyclerView 解析(二)

一、前言
RecyclerView 第二篇。这篇主要将 RecyclerView 的拖动,滑动。如果你还不了解RecyclerView ,建议你去读RecyclerView 解析(一)

二、代码:
1、先看一下效果:
这里写图片描述
要想实现这样的效果,在Android support V7包下为我们提供了一个类:ItemTouchHelper 所有RecyclerView Item上下左右拖动,滑动删除均可以利用这个类实现。

2、首先需要自定义类实现ItemTouchHelper.Callback

package recyclerdemo.li.com.recyclerdemo.main;

import android.graphics.Canvas;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;

/**
 * Created  lixin on 2016/4/27.
 */
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {

    private ItemTouchHelperAdapter mItemTouchHelperAdapter;

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


    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

        //针对ListView的支持
        int dragFlag = ItemTouchHelper.UP| ItemTouchHelper.DOWN;//上下拖动
        int swipFlag = ItemTouchHelper.START|ItemTouchHelper.END;//左右滑动
        //针对GridView的支持
//        int dragFlag = ItemTouchHelper.UP|ItemTouchHelper.DOWN|ItemTouchHelper.START|ItemTouchHelper.END;
//        int swipFlag = 0;
        return makeMovementFlags(dragFlag,swipFlag);
    }

    /**
     * 长按进入操作
     * @return
     */
    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }

    /**
     * 用于支持滑动
     * @return
     */
    @Override
    public boolean isItemViewSwipeEnabled() {
        return true;
    }

    /**
     * 移动
     * @param recyclerView
     * @param viewHolder
     * @param target
     * @return
     */
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        mItemTouchHelperAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

    /**
     * 移除
     * @param viewHolder
     * @param direction
     */
    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        mItemTouchHelperAdapter.onItemDismiss(viewHolder.getAdapterPosition());
    }

    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView,
                            RecyclerView.ViewHolder viewHolder, float dX, float dY,
                            int actionState, boolean isCurrentlyActive) {
        Log.d("test","dx : "+ dX +" dy : "+ dY);
        if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){
            float width = (float) viewHolder.itemView.getWidth();
            float alpha = 1.0f - Math.abs(dX) / width;
            viewHolder.itemView.setAlpha(alpha);
            viewHolder.itemView.setTranslationX(dX);
        }else{
            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
        }

    }


}

继承ItemTouchHelper.Callback 类需要重写一下几个方法:
(1)getMovementFlags()方法。
主要用于设置退拽以及滑动的方向。

//针对ListView的支持
        int dragFlag = ItemTouchHelper.UP| ItemTouchHelper.DOWN;//上下拖动
        int swipFlag = ItemTouchHelper.START|ItemTouchHelper.END;//左右滑动
//针对GridView的支持
        int dragFlag = ItemTouchHelper.UP|ItemTouchHelper.DOWN|ItemTouchHelper.START|ItemTouchHelper.END;
        int swipFlag = 0;

其中针对ListView,上下拖动,左右滑动删除。针对GridView排列方式,可以上下左右随意拖动,当swipFlag = 0 表示其不可以被滑动删除。
(2)isLongPressDragEnabled()返回True 表示长按进入操作。
(3)isItemViewSwipeEnabled()返回True表示支持滑动删除。
(4)onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)
第二个参数viewHolder 表示被拖动的元素。第三个元素target即表示其目标元素。
(5)onSwiped()移除
(6)onChildDraw()当发生拖动以及移除操作时,会不断的调用这个参数。其中参数dX dY即表示被拖动的所对应XY的距离。可以用这个方法加入一些动画。
(7)其中 ItemTouchHelperAdapter 为自定义接口:

package recyclerdemo.li.com.recyclerdemo.main;

/**
 * Created by lixin on 2016/4/27.
 */
public interface ItemTouchHelperAdapter {
    void onItemMove(int fromPosition, int toPosition);
    void onItemDismiss(int position);
}

在初始化SimpleItemTouchHelperCallback 时将其对象传入,用于在发生拖动以及删除时回调给Adapter,通知Adapter更新数据。
及我们自定义的Adapter需要实现ItemTouchHelperAdapter ,重写onItemMove ,onItemDismiss方法。

Adapter代码:

private class CustomAdapter extends RecyclerView.Adapter implements ItemTouchHelperAdapter {

        private OnStartDragListener mOnStartDragListener;

        public CustomAdapter(OnStartDragListener onStartDragListener){
            this.mOnStartDragListener = onStartDragListener;
        }


        @Override
        public int getItemCount() {
            return mData.size();
        }

        @Override
        public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            RecyclerHolder holder = new RecyclerHolder(LayoutInflater.from(MainActivity.this).inflate(R.layout.recycler_item2,parent,false));
            return holder;
        }

        @Override
        public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
            final RecyclerHolder rholder = (RecyclerHolder)holder;
            rholder.textView.setText(mData.get(position));

        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public void onItemDismiss(int position) {
            mData.remove(position);
            notifyItemRemoved(position);
            notifyDataSetChanged();
        }

        @Override
        public void onItemMove(int fromPosition, int toPosition) {
            Collections.swap(mData,fromPosition,toPosition);
            notifyItemMoved(fromPosition,toPosition);
        }
    }

    class RecyclerHolder extends RecyclerView.ViewHolder{

        TextView textView;
        Button button;

        public RecyclerHolder(View view){
            super(view);
            textView = (TextView)view.findViewById(R.id.text);
            button = (Button)view.findViewById(R.id.drag);
        }

    }

注意:在RecyclerView 中可以调用notifyItemInserted(int position)表示插入了一条元素,notifyItemRemoved(int position)表示有一条元素被删除了。其中position表示被加入以及删除的位置。而不再需要调用notifyDataSetChanged()方法。同样notifyItemMoved(int fromPosition,int toPosition);用于表示从哪个位置移动到了哪个位置。

3、在RecyclerView 初始化时:

//设置拖拽,移除
        ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(mAdapter);
        mItemTouchHelper = new ItemTouchHelper(callback);
        mItemTouchHelper.attachToRecyclerView(mRecyclerView);

4、综上所诉便可以实现RecyclerView的滑动以及删除。

三、总结:
RecyclerView 实现拖动以及删除可以利用ItemTouchHelper ,轻轻松松便可以实现效果。而且看ItemTouchHelper 的源码发现其是继承自RecyclerView.ItemDecoration 的。RecyclerView.ItemDecoration前文提到过,是用于实现分割线的。这是不是很有意思呢。好了,今天就写到这,有哪些不足,或者错误之处,欢迎指正。令下一篇会写RecyclerView相关一些开源库,并且探讨一下开源库内部是如何实现的。

四、参考资料:
泡在网上的日子
https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-b9456d2b1aaf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值