从Android源码入手解决ScrollView与内部控件的滑动冲突问题

ScrollView与内部控件滑动冲突的布局文件
如图所示,父布局是一个ScrollView,内部一个子View-SelectView是一个自定义的水平滑动的View,当手指放在SelectView上左右滑动时,会与ScrollView的上下滑动事件产生冲突。平时我们也会碰到类似的这种ScrollView与内部控件的滑动冲突问题,比如嵌套ListView等等,先来说说如何解决吧

SelectView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    //允许ScrollView拦截点击事件,ScrollView可滑动
                    ScrollView.requestDisallowInterceptTouchEvent(false);
      //SelectView.getParent().requestDisallowInterceptTouchEvent(false)//这种写法亦可
                } else {
                    //不允许ScrollView拦截点击事件,点击事件由子View处理
                    ScrollView.requestDisallowInterceptTouchEvent(true);
      //SelectView.getParent().requestDisallowInterceptTouchEvent(true)//这种写法亦可
                }
                return false;
            }
       });
注:其中SelectView是子View的控件id,ScrollView是父控件View的控件id

归根到底发生冲突的原因是View的事件分发机制,本来应该由子View-SelectView处理的事件被父控件ScrollView处理了,知道原因我们就可以着手解决了。在ScrollView或者说ViewGroup中提供了这样一个方法requestDisallowInterceptTouchEvent(boolean disallowIntercept),翻译成中文就是请求不允许拦截点击事件,我们来看下源码:

@Override
 public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
     if (disallowIntercept) {
         recycleVelocityTracker();
     }
     super.requestDisallowInterceptTouchEvent(disallowIntercept);
 }

内部调用了recycleVelocityTracker()方法,我们继续来看源码

private void recycleVelocityTracker() {
        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }

recycleVelocityTracker()内部调用了recycle()方法,我们继续来看源码

/**
 * Return a VelocityTracker object back to be re-used by others.  You must
 * not touch the object after calling this function.
 */
public void recycle() {
    if (mStrategy == null) {
        clear();
        sPool.release(this);
    }
}

看到这一层的官方注释相信大家应该明白了,翻译过来的意思就是:返回一个VelocityTracker对象,让其他人重新使用它,在调用这个函数之后,你不能再碰这个对象。通俗点说就是:VelocityTracker对象回收后代表你不需要使用了,系统将此对象重新分配到其他请求者。反过来我们再看文章开头的解决方法大家应该都能明白了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值