1

现在RecyclerView都使用的相对频繁了,在开始使用RecyclerView的时候,大家都应该都遇到过RecyclerView居然没有帮我们实现Item点击事件,顿时感觉不知所措了。查阅API发现确实没有实现该事件,最后经过苦思冥想,还是模仿ListView的点击事件,在onCreateViewHolder中为每个Item添加ViewsetOnClickListener事件,制定一个接口,在主函数中调用。瞬间解决了,一下感觉so easy。但是这样真的好吗?我们想想一旦Item的数量暴增这可会影响性能啊。所以我们应该想出别的方法来代替它,下面我就介绍另外一种高大上的方法来教你如何真正的为RecyclerViewItem添加点击事件。

原理

虽然RecyclerView没有帮我们实现相应的点击监听事件,但我们查询它的API会发现它有一个方法帮我们实现了,就是addOnItemTouchListener触摸实事件,我们可以借助该监听来根据我们的触摸反应帮我们实现相同的点击事件效果。当然其中我们还要借助GestureDetectorCompat根据触摸手势来判断是否为点击事件。

addOnItemTouchListener

RecyclerView添加addOnItemTouchListener

recyclerView.addOnItemTouchListener(new OnItemTouchListener(recyclerView) {
            @Override
            public void onItemClick(RecyclerView.ViewHolder vh) {
            //item 操作
            }
        });

这里我们要自定义去实现RecyclerView.OnItemTouchListener接口

实现OnItemTouchListener

在实现该接口时我们会发现有三个方法

  • onTouchEvent
  • onInterceptTouchEvent
  • onRequestDisallowInterceptTouchEvent

第一个是处理触摸事件的,第二个是拦截触摸事件的,第三个是处理触摸冲突的。第三个这里我们用不到,不用管,至于前两个我们只要向下面我们用到的GestureDetectorCompat传递MotionEvent为了获取触摸的坐标,最后再定义个abstract回调

public abstract class OnItemTouchListener implements RecyclerView.OnItemTouchListener {

    private GestureDetectorCompat mGestureDetectorCompat;
    private RecyclerView mRecyclerView;

    public OnItemTouchListener(RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
        mGestureDetectorCompat = new GestureDetectorCompat(mRecyclerView.getContext(),
                new MyGestureListener());
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        mGestureDetectorCompat.onTouchEvent(e);
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        mGestureDetectorCompat.onTouchEvent(e);
        return false;
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }

    public abstract void onItemClick(RecyclerView.ViewHolder vh);

GestureDetectorCompat

上面我们实例化了GestureDetectorCompat类其中第二个参数是手势监听OnGestureListener,但我们不需要使用它,我们可以实现它的一个简单的封装类SimpleOnGestureListener它里面实现的都的空操作,所以我们可以自己实现特定的方法来执行我们的操作。

SimpleOnGestureListener

这里我们只要实现其中的两个方法

  • onSingleTapUp
  • onLongPress

其中第一个是简单的点击屏幕时执行,第二个是长按屏幕时执行。所以根据这两个方法,我们就可以从前面OnItemTouchListener传过来的MotionEvent获取点击的位置,根据位置使用RecyclerViewfindChildViewUnder获取到点击的ItemView,再通过RecyclerViewgetChildViewHolder获取ItemViewViewHolder最后再调用OnItemClick方法。

private class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            View childe = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
            if (childe != null) {
                RecyclerView.ViewHolder VH = mRecyclerView.getChildViewHolder(childe);
                onItemClick(VH);
            }
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            View childe = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
            if (childe != null) {
                RecyclerView.ViewHolder VH = mRecyclerView.getChildViewHolder(childe);
                onItemClick(VH);
            }
        }
    }

好了整个的实现过程就是这些,看了以后是不是感觉更高大上了呢。如果对RecyclerView还不是很熟悉的可以先看我前面的这篇文章RecyclerView深入浅出

欢迎访问blog:https://idisfkj.github.io/

关注

clipboard.png


午后一小憩
2.9k 声望838 粉丝