RecyclerView实现长按、拖拉、滑动、选中、分割线

来源:互联网 发布:mac 退出全屏快捷键 编辑:程序博客网 时间:2024/06/07 17:53

      • 长按
      • 拖动侧滑选中
      • 下滑线
  • 一个可以参考一下的便签app 还没完善全部功能

长按

  • RecyclerView没有提供监听点击事件的接口,没有mRecyclerView.setOn…,但是可以实现一个实现了RecyclerView.OnItemTouchListener接口的监听抽象类,然后调用RecyclerView的addOnItemTouchListener的方法给RecyclerView设置点击的监听。
  • 默认的时候,view的事件序列是会被TouchEvent截获的,而TouchEvent不提供双击和长按,想让view具备响应双击和长按,需要创建一个实现GestureDetector的接口的类,然后在TouchEvent里让这个类的实例来接收事件。所以,RecyclerView也一样,它需要在内部给自己创建一个这样的类,然后在自己的TouchEvent方法里接收事件序列。
  • 无论是给RecyclerView设置点击监听,还是为点击监听设置GestureDetecor,还是为GestureDetector设置回调,都只是让它们具备了基本的能力,具体的逻辑能力需要自己写。
    总的思路就是:
    1.为RecyclerView添加OnItemTouchListener,让RecyclerView具备事件分发
    2.为ReyeclerView的事件分发设置GestureDetector,让RecyclerView可以响应双击或者长按等
    3.在GestureDetector的具体实现里,结合RecyclerView的2个方法判断出具体的子项
    4.判断出具体的子项之后,用回调函数交给RecyclerView实例做处理;

点击事件监听类的实现:

  /** * Created by  on 2017/9/19. */public abstract class OnRecyclerItemClickListener implements RecyclerView.OnItemTouchListener{    private RecyclerView mRecyclerView;    private GestureDetectorCompat mGestureDetectorCompat;    /**     * 在创建实例的时候,传进指定的RecyclerView实例     * 同时使用实现了GestureDetector.SimpleOnGestureListener接口的类实例来创建GestureDetector     * @param recyclerView     */    public OnRecyclerItemClickListener(RecyclerView recyclerView) {        mRecyclerView = recyclerView;        mGestureDetectorCompat = new GestureDetectorCompat(mRecyclerView.getContext(),new ItemTouchHelperGestureListener());    }    /**     * 重写下面三个方法,让GestureDetector接收事件     * @param rv     * @param e     * @return     */    @Override    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {        mGestureDetectorCompat.onTouchEvent(e);        return false;    }    @Override    public void onTouchEvent(RecyclerView rv, MotionEvent e) {        mGestureDetectorCompat.onTouchEvent(e);    }    @Override    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {    }    /**     * 需要调用者,也就是RecyclerView实例实现的抽象方法     * @param viewHolder     */    public abstract void onItemClick(RecyclerView.ViewHolder viewHolder);    public abstract void onLongClick(RecyclerView.ViewHolder viewHolder);    /**     * 实现一个GestureDetector,重写关于单点和长按方法     */    private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener{        @Override        public boolean onSingleTapUp(MotionEvent e) {            //通过点击事件的坐标,用findChileViewUnder找到被点击的view            View childViewUnder = mRecyclerView.findChildViewUnder(e.getX(),e.getY());            if (childViewUnder != null){                //通过被点击的view,用getChildViewHolder找到被点击的viewHolder                RecyclerView.ViewHolder childViewHolder = mRecyclerView.getChildViewHolder(childViewUnder);                onItemClick(childViewHolder); //回调            }            return true;        }        @Override        public void onLongPress(MotionEvent e) {            View chileViewUnder = mRecyclerView.findChildViewUnder(e.getX(),e.getY());            if (chileViewUnder != null){                RecyclerView.ViewHolder childViewHolder = mRecyclerView.getChildViewHolder(chileViewUnder);                onLongClick(childViewHolder);            }        }    }}

具体的使用:

public class Listener extends OnRecyclerItemClickListener{            public Listener(RecyclerView recyclerView){                super(recyclerView);            }            @Override            public void onItemClick(RecyclerView.ViewHolder viewHolder) {                //do someting;            }            @Override            public void onLongClick(RecyclerView.ViewHolder viewHolder) {                //do something;            }}Listener listener = new Listener(mRecyclerView);mRecyclerView.addOnItemTouchListener(listener);

或者使用匿名内部类的方式:

mRecyclerView.addOnItemTouchListener(new OnRecyclerItemClickListener(mRecyclerView) {            @Override            public void onItemClick(RecyclerView.ViewHolder viewHolder) {                //do someting;            }            @Override            public void onLongClick(RecyclerView.ViewHolder viewHolder) {                //do something;            }        });

拖动、侧滑、选中

拖动可以使用ItemTouchHelper来实现,它的内部封装了很多的接口,包括拖动、侧滑、选中等等,我们只要将需要实现这些功能的view(不仅仅是RecyclerView)设置给它,然后自己实现接口里需要的逻辑就行了。
比如,实现回调接口类:

public class Call implements ItemTouchHelper.Callback{    //@Override 重写需要的方法;    ...}

然后用这个类的实例来创建ItemTouchHelper实例,再将RecyclerView或者其他的view设置给ItemTouchHelper实例

ItemTouchHelper helper = new ItemTouchHelper(new Call());helper.attachToRecyclerView(mRecyclerView);

ItemTouchHelper.Callback的重写例子:

/** * Created by  on 2017/9/19. */public class ItemTouchCallback extends ItemTouchHelper.Callback {    private NoteAdaper mNoteAdaper;    public ItemTouchCallback(){        super();    }    /**     * 通过使用RecyclerView的适配器来操作RecyclerView     * @param noteAdaper     */    public ItemTouchCallback(NoteAdaper noteAdaper){        mNoteAdaper = noteAdaper;    }    /**     * 这个方法用于决定哪些方向的滑动是允许的,或者说是可以引起响应的     * @param recyclerView     * @param viewHolder     * @return  int 返回一个整型,标志是否允许滑动     */    @Override    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {        //如果是线性的,设置拖拉方向为上和下,侧滑为左和右        if (recyclerView.getLayoutManager() instanceof LinearLayoutManager){            int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;            int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;            return makeMovementFlags(dragFlags,swipeFlags);        }else{  //如果是表格性的,设置上下左右四个方向            if (recyclerView.getLayoutManager()instanceof GridLayoutManager){                int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN                        |ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;                int swipeFlags = 0;  //0代表不滑动                return makeMovementFlags(dragFlags,swipeFlags);            }        }        return 0;    }    /**     * 这个方法响应拖动事件     * @param recyclerView     * @param viewHolder  被拖动的viewHolder     * @param target   位置被代替的viewHolder     * @return     */    @Override    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {        int fromPostion = viewHolder.getAdapterPosition();        int toPosition = target.getAdapterPosition();        //如果子项是向下托拉,从拖拉位置开始的地方到目标位置的前一个位置,全部子项向后一个子项交换数据        if (fromPostion < toPosition){            for (int i = fromPostion; i < toPosition; i ++){                Collections.swap(mNoteAdaper.getDataList(),i,i + 1);            }        }else { //如果子项是向上拖拉,从拖拉位置开始到目标位置的下一个位置,全部子项向前一个子项交换数据            for (int i = fromPostion; i > toPosition; i--){                Collections.swap(mNoteAdaper.getDataList(),i,i - 1);            }        }        //上一步交换完数据,这一步交换视图        mNoteAdaper.notifyItemMoved(fromPostion,toPosition);        return true;    }    /**     * 这个方法响应侧滑     * @param viewHolder  被滑动的子项     * @param direction  滑动方向,可以根据不同的方向做不同的事情     */    @Override    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {        int adapterPosition = viewHolder.getAdapterPosition();  //获得被侧滑的子项位置        mNoteAdaper.notifyItemRemoved(adapterPosition);  //视图清除        mNoteAdaper.getDataList().remove(adapterPosition);  //数据清除    }    /**     * 响应选中     * @param viewHolder  被选中的子项     * @param actionState  子项的选中状态,可以根据子项的选中状态做不同的处理     */    @Override    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE){  //ItemTouchHelper.ACTION_STATE_IDLE 空闲状态            viewHolder.itemView.setBackground(MyApplication.getContext().getDrawable(R.drawable.gray));        }        super.onSelectedChanged(viewHolder, actionState);    }    /**     * 这个方法用于当拖动、侧滑、选中等等动作消失后,需要做的处理     * @param recyclerView     * @param viewHolder  被操作的子项     */    @Override    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {        super.clearView(recyclerView, viewHolder);        viewHolder.itemView.setBackground(MyApplication.getContext().getDrawable(R.drawable.white));    }}

使用例子:

    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchCallback(mNoteAdaper));    itemTouchHelper.attachToRecyclerView(mRecyclerView);

下滑线

方式1:
创建一个drawable对象,然后在子项布局的底部加一个ImageView,然后设置这个drawable对象为背景,drawable对象:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android">    <solid android:color="@color/gray"/>    <size android:height="1px"/></shape>

方式2:
使用RecyclerView的addItemDecoration方法:

mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));

一个可以参考一下的便签app (还没完善全部功能)

原创粉丝点击