RecyclerView事件拦截

本文主要分析RecyclerView的onInterceptTouchEvent()对三种事件怎么处理的
这里只放了一些比较重要点的代码,有一部分省略

先看onInterceptTouchEvent()的返回值

return mScrollState == SCROLL_STATE_DRAGGING

解释一下mScrollState这个变量,代表RecyclerView的滑动状态,它一共有三种值

    public static final int SCROLL_STATE_IDLE = 0; // 滑动停止
    public static final int SCROLL_STATE_DRAGGING = 1; //正在被用户滑动
    public static final int SCROLL_STATE_SETTLING = 2;//正在自动滑动,这个大家日常应该都遇到过,当我们快速滑动然后抬起手时会发生自动滑动

ACTION_DOWN

   @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
         ...
        switch (action) {
            case MotionEvent.ACTION_DOWN:
             ...
                if (mScrollState == SCROLL_STATE_SETTLING) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                    setScrollState(SCROLL_STATE_DRAGGING);
                    stopNestedScroll(TYPE_NON_TOUCH);
                }
                ...
                break;

             ...
        }
        
        return mScrollState == SCROLL_STATE_DRAGGING;
    }

down事件主要看中间的判断部分,如果当前的滑动状态是自动滑动(SCROLL_STATE_SETTLING)状态,则将滑动状态置为正在滑动(SCROLL_STATE_DRAGGING),然后停止滑动,这样就对down事件做了拦截,其实很好理解:当你的列表在自动快速滚动的过程中,手指再按上去,是需要停止滑动的;
所以只有这种情况RecyclerView才会拦截down事件,其他情况分发给子view

ACTION_MOVE

            case MotionEvent.ACTION_MOVE: {
               ...
                final int x = (int) (e.getX(index) + 0.5f);
                final int y = (int) (e.getY(index) + 0.5f);
                if (mScrollState != SCROLL_STATE_DRAGGING) {
                    final int dx = x - mInitialTouchX;
                    final int dy = y - mInitialTouchY;
                    boolean startScroll = false;
                    if (canScrollHorizontally && Math.abs(dx) > mTouchSlop) {
                        mLastTouchX = x;
                        startScroll = true;
                    }
                    if (canScrollVertically && Math.abs(dy) > mTouchSlop) {
                        mLastTouchY = y;
                        startScroll = true;
                    }
                    if (startScroll) {
                        setScrollState(SCROLL_STATE_DRAGGING);
                    }
                }
            } break;

move事件处理就很好理解了,如果当前滚动状态是正在滑动,就直接拦截;如果不是,则判断x轴和y轴上滑动距离是否超过最小滑动距离,超过了就将滚动状态置为正在滑动状态,然后拦截;

ACTION_UP

            case MotionEvent.ACTION_UP: {
                mVelocityTracker.clear();
                stopNestedScroll(TYPE_TOUCH);
            } break;

up事件除了停止滑动什么也没干,如果当前是正在滑动状态直接拦截,否则分发子view

总结

RecyclerView对三种事件的处理:
down事件:如果当前处于自动滚动状态,则拦截事件,停止滚动,否则分发给子view
move事件:如果当前处于正在滑动状态直接拦截,否则判断水平与竖直滑动距离是否超过最小滑动距离(mTouchSlop),超过则拦截,否则不拦截
up事件:只做了停止滑动操作,是否拦截依赖当前滑动状态

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值