您的位置:首页 > 其它

MotionEvent事件在onInterceptTouchEvent()、onTouchEvent()中的传递顺序

2014-03-27 09:52 483 查看

MotionEvent事件在onInterceptTouchEvent()、onTouchEvent()中的传递顺序

onInterceptTouchEvent()用于处理事件并改变事件的传递方向。处理事件这个不用说了,你在函数内部编写代码处理就可以了。而决定传 递方向的是返回值,返回为false时事件会传递给子控件的onInterceptTouchEvent();返回值为true时事件会传递给当前控件的 onTouchEvent(),而不在传递给子控件,这就是所谓的Intercept(截断)。

onTouchEvent() 用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。可能你要问是否消费了又区别吗,反正我已经针对事件编写了处理代码?答案是有区 别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么 系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。

<?xml version="1.0" encoding="utf-8"?>

<com.touchstudy.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent" >

    <com.touchstudy.LayoutView2

        android:orientation="vertical"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:gravity="center">

       <com.touchstudy.MyTextView

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:id="@+id/tv"

            android:text="AB"

            android:textSize="40sp"

            android:textStyle="bold"

            android:background="#FFFFFF"

            android:textColor="#0000FF"/>

   </com.touchstudy.LayoutView2>

</com.touchstudy.LayoutView1>

复制代码
在没有重写onInterceptTouchEvent()和onTouchEvent()的情况下(他们的返回值都是false), 对上面这个布局,MotionEvent事件的传递顺序如下:



当某个控件的onInterceptTouchEvent()返回值为true时,就会发生截断,事件被传到当前控件的onTouchEvent()。如我们将LayoutView2的onInterceptTouchEvent()返回值为true,则传递流程变成:



如果我们同时将LayoutView2的onInterceptTouchEvent()和onTouchEvent()设置成true,那么 LayoutView2将消费被传递的事件,同时后续事件(如跟着ACTION_DOWN的ACTION_MOVE或者ACTION_UP)会直接传给 LayoutView2的onTouchEvent(),不传给其他任何控件的任何函数。同时传递给子空间一个ACTION_CANCEL事件。传递流程 变成(图中没有画出ACTION_CANCEL事件):


          


附SDK给出的说明:

·  You will receive the down event here.

·  The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking
for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.

·  For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().

·  If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.

[align=left]由于onInterceptTouchEvent()的机制比较复杂,上面的说明写的也比较复杂,总结一下,基本的规则是:[/align]
[align=left]1.       down事件首先会传递到onInterceptTouchEvent()方法[/align]
[align=left]2.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。[/align]
[align=left]3.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的 onTouchEvent()处理,注意,目标view将接收不到任何事件。[/align]
[align=left]4.       如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。[/align]
[align=left]5.       如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。[/align]

[align=left]下面用一个简单的实验说明上述复杂的规则。视图自底向上共3层,其中LayoutView1和LayoutView2就是LinearLayout, MyTextView就是TextView:[/align]
[align=left]对应的xml布局文件如下:[/align]

<?xml version="1.0" encoding="utf-8"?>

<com.touchstudy.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent" >

    <com.touchstudy.LayoutView2

        android:orientation="vertical"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:gravity="center">

       <com.touchstudy.MyTextView  

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:id="@+id/tv"

            android:text="AB"

            android:textSize="40sp"

            android:textStyle="bold"

            android:background="#FFFFFF"

            android:textColor="#0000FF"/>

   </com.touchstudy.LayoutView2>

</com.touchstudy.LayoutView1>

复制代码
[align=left]下面看具体情况:[/align]
[align=left]1.       onInterceptTouchEvent()处理down事件均返回false,onTouchEvent()处理事件均返回true[/align]
[align=left]------------------------------------------------------------------------------------------------------------------------------[/align]
[align=left]04-11 03:58:42.620: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_DOWN[/align]
04-11 03:58:42.620: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_DOWN
[align=left]04-11 03:58:42.620: DEBUG/MyTextView(614): onTouchEvent action:ACTION_DOWN[/align]
[align=left]04-11 03:58:42.800: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_MOVE[/align]
[align=left]04-11 03:58:42.800: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_MOVE[/align]
[align=left]04-11 03:58:42.800: DEBUG/MyTextView(614): onTouchEvent action:ACTION_MOVE[/align]
[align=left]…… //省略过多的ACTION_MOVE[/align]
[align=left]04-11 03:58:43.130: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_UP[/align]
[align=left]04-11 03:58:43.130: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_UP[/align]
[align=left]04-11 03:58:43.150: DEBUG/MyTextView(614): onTouchEvent action:ACTION_UP[/align]
[align=left]------------------------------------------------------------------------------------------------------------------------------[/align]
[align=left]这 是最常见的情况,onInterceptTouchEvent并没有做任何改变事件传递时序的操作,效果上和没有覆写该方法是一样的。可以看到,各种事件 的传递本身是自底向上的,次序是:LayoutView1->LayoutView2->MyTextView。注意,在onInterceptTouchEvent均返回false时,LayoutView1和LayoutView2的onTouchEvent并不会收到事件,而是最终传递给了MyTextView。[/align]

[align=left]2.     LayoutView1的onInterceptTouchEvent()处理down事件返回true,[/align]
[align=left]MyTextView的onTouchEvent()处理事件返回true[/align]
[align=left]------------------------------------------------------------------------------------------------------------------------------[/align]
[align=left]04-11 03:09:27.589: DEBUG/LayoutView1(446): onInterceptTouchEvent action:ACTION_DOWN[/align]
[align=left]04-11 03:09:27.589: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_DOWN[/align]
[align=left]04-11 03:09:27.629: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_MOVE[/align]
[align=left]04-11 03:09:27.689: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_MOVE[/align]
[align=left]…… //省略过多的ACTION_MOVE[/align]
[align=left]04-11 03:09:27.959: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_UP[/align]
[align=left]------------------------------------------------------------------------------------------------------------------------------[/align]
[align=left]从Log可以看到,由于LayoutView1在拦截第一次down事件时return true,所以后续的事件(包括第一次的down)将由LayoutView1本身处理,事件不再传递下去。[/align]

[align=left]3.       LayoutView1,LayoutView2的onInterceptTouchEvent()处理down事件返回false,[/align]
[align=left]MyTextView的onTouchEvent()处理事件返回false[/align]
[align=left]LayoutView2的onTouchEvent()处理事件返回true[/align]
[align=left]----------------------------------------------------------------------------------------------------------------------------[/align]
[align=left]04-11 09:50:21.147: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_DOWN[/align]
[align=left]04-11 09:50:21.147: DEBUG/LayoutView2(301): onInterceptTouchEvent action:ACTION_DOWN[/align]
[align=left]04-11 09:50:21.147: DEBUG/MyTextView(301): onTouchEvent action:ACTION_DOWN[/align]
[align=left]04-11 09:50:21.147: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_DOWN[/align]
[align=left]04-11 09:50:21.176: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_MOVE[/align]
[align=left]04-11 09:50:21.176: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_MOVE[/align]
[align=left]04-11 09:50:21.206: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_MOVE[/align]
[align=left]04-11 09:50:21.217: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_MOVE[/align]
[align=left]…… //省略过多的ACTION_MOVE[/align]
[align=left]04-11 09:50:21.486: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_UP[/align]
[align=left]04-11 09:50:21.486: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_UP[/align]
[align=left]----------------------------------------------------------------------------------------------------------------------------[/align]
[align=left]可 以看到,由于MyTextView在onTouchEvent()中return false,down事件被传递给其父view,即LayoutView2的onTouchEvent()方法处理,由于在LayoutView2的 onTouchEvent()中return true,所以down事件传递并没有上传到LayoutView1。注意,后续的move和up事件均被传递给LayoutView2的onTouchEvent()处理,而没有传递给MyTextView。[/align]

[align=left]源代码贴上,其实很简单,就是基础文件,主要是用来观察事件的传递。[/align]

[align=left]主Activity: InterceptTouchStudyActivity.java:[/align]

public class InterceptTouchStudyActivity extends Activity {

    static final String TAG = "ITSActivity";

    TextView tv;

   

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.layers_touch_pass_test);

     }

}

      LayoutView1.java:

      public class LayoutView1 extends LinearLayout {

             private final String TAG = "LayoutView1";

               public LayoutView1(Context context, AttributeSet attrs) {

         super(context, attrs);

         Log.d(TAG,TAG);

     }

     @Override

     public boolean onInterceptTouchEvent(MotionEvent ev) {

         int action = ev.getAction();

         switch(action){

         case MotionEvent.ACTION_DOWN:

              Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");

//            return true;

              break;

         case MotionEvent.ACTION_MOVE:

              Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");

              break;

         case MotionEvent.ACTION_UP:

              Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");

              break;

         case MotionEvent.ACTION_CANCEL:

              Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");

              break;

         }

         

         return false;

     }

     @Override

     public boolean onTouchEvent(MotionEvent ev) {

         int action = ev.getAction();

         switch(action){

         case MotionEvent.ACTION_DOWN:

              Log.d(TAG,"onTouchEvent action:ACTION_DOWN");

              break;

         case MotionEvent.ACTION_MOVE:

              Log.d(TAG,"onTouchEvent action:ACTION_MOVE");

              break;

         case MotionEvent.ACTION_UP:

              Log.d(TAG,"onTouchEvent action:ACTION_UP");

              break;

         case MotionEvent.ACTION_CANCEL:

              Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");

              break;

         }

         

         return true;

     }

     @Override

     protected void onLayout(boolean changed, int l, int t, int r, int b) {

         // TODO Auto-generated method stub

         super.onLayout(changed, l, t, r, b);

     }

     @Override

     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

         // TODO Auto-generated method stub

         super.onMeasure(widthMeasureSpec, heightMeasureSpec);

     }

}

LayoutView2.java:

public class LayoutView2 extends LinearLayout {

    private final String TAG = "LayoutView2";

   

    public LayoutView2(Context context, AttributeSet attrs) {

       super(context, attrs);

       Log.d(TAG,TAG);

    }

    @Override

    public boolean onInterceptTouchEvent(MotionEvent ev) {

       int action = ev.getAction();

       switch(action){

       case MotionEvent.ACTION_DOWN:

           Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");

           break;

       case MotionEvent.ACTION_MOVE:

           Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");

           break;

       case MotionEvent.ACTION_UP:

           Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");

           break;

       case MotionEvent.ACTION_CANCEL:

           Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");

           break;

       }

      

       return false;

    }

    @Override

    public boolean onTouchEvent(MotionEvent ev) {

       int action = ev.getAction();

       switch(action){

       case MotionEvent.ACTION_DOWN:

           Log.d(TAG,"onTouchEvent action:ACTION_DOWN");

           break;

       case MotionEvent.ACTION_MOVE:

           Log.d(TAG,"onTouchEvent action:ACTION_MOVE");

           break;

       case MotionEvent.ACTION_UP:

           Log.d(TAG,"onTouchEvent action:ACTION_UP");

           break;

       case MotionEvent.ACTION_CANCEL:

           Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");

           break;

       }

      

       return true;

    }

}

MyTextView.java:

public class MyTextView extends TextView {

    private final String TAG = "MyTextView";

   

    public MyTextView(Context context, AttributeSet attrs) {

       super(context, attrs);

       Log.d(TAG,TAG);

    }

    @Override

    public boolean onTouchEvent(MotionEvent ev) {

       int action = ev.getAction();

       switch(action){

       case MotionEvent.ACTION_DOWN:

           Log.d(TAG,"onTouchEvent action:ACTION_DOWN");

           break;

       case MotionEvent.ACTION_MOVE:

           Log.d(TAG,"onTouchEvent action:ACTION_MOVE");

           break;

       case MotionEvent.ACTION_UP:

           Log.d(TAG,"onTouchEvent action:ACTION_UP");

           break;

       case MotionEvent.ACTION_CANCEL:

           Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");

           break;

       }

      

       return false;

    }

   

    public void onClick(View v) {

       Log.d(TAG, "onClick");

    }

   

    public boolean onLongClick(View v) {

       Log.d(TAG, "onLongClick");

       return false;

    }

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐