onInterceptTouchEvent与onTouchEvent
之前练习自定义ViewGroup时,用到了onInterceptTouchEvent方法,这个方法与onTouchEvent容易搞不清,特此分享一下这两个方法的使用方法。
1、onInterceptTouchEvent()是用于处理事件,其返回值决定是否允许Touch事件继续向下(子控件)传递。返回True(代表事件在当前的viewGroup中会被处理),则向下传递之路被截断(所有子控件将没有机会参与Touch事件),同时把事件传递给当前的控件的onTouchEvent()处理;返回false,则把事件交给子控件的onInterceptTouchEvent(),以此类推。
2、onTouchEvent()用于处理事件,其返回值决定当前控件是否消费了这个事件,是否还允许Touch事件继续向上(父控件)传递。返回false,则向上传递给父控件。返回true,如果是子控件返回true,那么它的touch事件都在这里处理,父控件是处理不了,因为它收不到子控件传给他的touch,被子控件给拦截了。
PS:是否消费对处理是否有影响?有的,比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。
由此概念,我们大概能知道其区别了,onInterceptTouchEvent处理的事件是从父控件开始往子控件传的,直到有拦截或者到没有这个事件的view,然后就往回从子控件到父控件,从子控件到父控件则是由onTouchEvent来负责,两者的关系算是紧密相连的。由此我们也可以知道onInterceptTouchEvent是针对于有childview的ViewGroup才有的方法,onTouchEvent则是所有view都有的方法。
我们用一个小例子来说明这两者的工作方式:
1 <com.example.LayoutView1 2 xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" 5 android:orientation="vertical" > 6 7 <com.example.LayoutView2 8 android:layout_width="fill_parent" 9 android:layout_height="fill_parent" 10 android:gravity="center" 11 android:orientation="vertical" > 12 13 <com.example.MyTextView 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" /> 16 </com.example.LayoutView2> 17 </com.example.LayoutView1>
这个简单的布局在手机上大概是这么个层级关系:
通常外围的layoutview1,layoutview2只是布局的容器不需要响应触屏的点击事件,仅仅Mytextview需要相应点击。但这只是一般情况,一些特殊的布局可能外围容器也要响应(比如说下拉刷新的ViewGroup),甚至不让里面的mytextview去响应。更有特殊的情况是,动态更换响应对象。那么首先看一下默认的触屏事件的在两个函数之间的传递流程。如下图:
我们以最常见的down事件来说明
-
down事件首先会传递到onInterceptTouchEvent()方法
-
如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
-
如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
-
如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
-
如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。
我们来看看layoutview1的onInterceptTouchEvent若返回true的流程: