案例开头是要先装会比的,但是今天例外,because .....
说到滑动冲突,真tm是个让人蛋疼的问题,下面 我来给大家 浅浅的谈谈我的理解。
scrollview 是个好东西吧,对的,没错,他可以让我们的布局滑动起来,提现它的优美,这时,突然在它里面 出现了一个viewpager , 然后我们run 一下程序,恩,发现一切还是那么优美,然后我们轻轻用手滑动一下屏幕,what the fox say? 为毛我下拉 viewpager 整个屏幕没反应,什么鬼,一定有bug,哈哈哈,我发现了谷歌的一个bug,好了,别装逼了,产品经理催着你搞呢...
遇到这么一个B问题,莫慌,我来带领你实现翻盘计划, 首先在 解决整个问题之前,你首先并且必须要 深入理解一下 android touch 事件 的分发机制,
看到上面这张图了吧,没错,是我从网上抄的,咳咳,,
Touch事件分发中只有两个主角:ViewGroup和View。
ViewGroup 可以简单的理解有 3个 touch事件相关的方法:
1.onInterceptTouchEvent
2.dispatchTouchEvent
3.onTouchEvent
View 可以简单的理解有 2个 touch事件相关的方法:
1.dispatchTouchEvent
2.onTouchEvent
ok,重点来了,
1. onInterceptTouchEvent这个方法 是拦截touch 事件方法,你可以想,作为viewgroup,我需要向我下面的子view 下达touch事件命令,当然我有权 对下达的命令做更改,
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { return super.onInterceptTouchEvent(ev); }
作为一个boolean 返回类型的方法,当返回false 时,表示touch事件可以继续向子view传递,当返回true时,表示 touch事件被拦截,已经消耗,并不在往下传递, 举个例子:Linearlayout 下有个 button控件, 如果我重写Linearlayout 的 onInterceptTouchEvent ,并且直接return true, 你再去调用button的点击事件,会发现点击事件失效,当然 onInterceptTouchEvent 作用仅仅如此,决定touch事件是否继续向下传递。
2. dispatchTouchEvent方法只负责事件的分发,它拥有boolean类型的返回值,当返回为true时,顺序下发会中断。在上述例子中如果⑤的dispatchTouchEvent返回结果为true,那么⑥-⑦-③-④将都接收不到本次Touch事件。当一个Touch事件(触摸事件为例)到达根节点,即Acitivty的ViewGroup时,它会依次下发,下发的过程是调用子View(ViewGroup)的dispatchTouchEvent方法实现的。简单来说,就是ViewGroup遍历它包含着的子View,调用每个View的dispatchTouchEvent方法,而当子View为ViewGroup时,又会通过调用ViwGroup的dispatchTouchEvent方法继续调用其内部的View的dispatchTouchEvent方法。上述例子中的消息下发顺序是这样的:①-②-⑤-⑥-⑦-③-④。
3.onTouchEvent,这个作为 比较重要的一个事件,需要详讲,ViewGroup的onTouchEvent事件是什么时候处理的呢?当ViewGroup所有的子View都返回false时,onTouchEvent事件便会执行。由于ViewGroup是继承于View的,它其实也是通过调用View的dispatchTouchEvent方法来执行onTouchEvent事件。 一般对于touch 事件的 move down 等,放在 onTouchEvent 里面处理。
好的,知道了以上3个方法都是干什么的了,那么天下间的 所有滑动冲突都将迎刃而解, 首先,我们先来 解决一开始的问题,
scrollview 嵌套viewpager 导致 的, 我在上下滑动viewpager的时候,scrollview 没响应 , 简单!
解决的办法也很简单,重写父scrollview 的 拦截事件,给定一定的条件,决定touch事件是否向下传递,比如,我们重写scrollview 的 onInterceptTouchEvent 方法, 判定用户的手势,当手势仅仅是上下滑动的时候,直接return true,消耗掉此次的touch事件,如此一来,就不会传递给 下面的viewpager 让其消耗了,
或者重写子viewpager 的touch事件 ,给定一定条件,决定是否消耗此次 touch ,比如,我们重写viewpager 的 onTouchEvent方法,判定用户的手势,如果是横向移动,就返回 true 消耗此次事件, 如果是 竖直移动 就返回false ,表示把此次事件的决定权返回给 父的scrollview 来处理,这样就解决了 传说中的 滑动冲突!!!!
有没有很6,自我感觉,真tm666666!