转:onTouchEvent和onInterceptTouchEvent详细研究

来源:互联网 发布:.net 数组包含 编辑:程序博客网 时间:2024/05/01 12:29

onTouchEvent和onInterceptTouchEvent详细研究

面试的时候曾被问过这两个方法的调用顺序,当时也只是知道onInterceptTouchEvent在前,具体的执行过程,相互的影响却不知道.今天写了一个小demo详细研究了一下这两个方法之间的关系.

首先上代码:

主activity:InterceptTouchStudyActivity

package com.touchstudy;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class InterceptTouchStudyActivity extends Activity {

    TextView tv;

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

    }

}

 布局文件main.xml

<?xml version="1.0" encoding="utf-8"?>
<com.touchstudy.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <com.touchstudy.LayoutView2
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center"
        android:orientation="vertical" >

        <com.touchstudy.MyTextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#FFFFFF"
            android:text="AB"
            android:textColor="#0000FF"
            android:textSize="40sp"
            android:textStyle="bold" />
    </com.touchstudy.LayoutView2>

</com.touchstudy.LayoutView1>

 类LayoutView1

package com.touchstudy;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;

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, "onInterceptTouchEvent1 action:ACTION_DOWN");

                // return true;

                break;

            case MotionEvent.ACTION_MOVE:

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

                break;

            case MotionEvent.ACTION_UP:

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

                break;

            case MotionEvent.ACTION_CANCEL:

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

                break;

        }
        boolean b = false;
        Log.d(TAG, "onInterceptTouchEvent1 return:"+b);
        return b;

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        int action = ev.getAction();

        switch (action) {

            case MotionEvent.ACTION_DOWN:

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

                break;

            case MotionEvent.ACTION_MOVE:

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

                break;

            case MotionEvent.ACTION_UP:

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

                break;

            case MotionEvent.ACTION_CANCEL:

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

                break;

        }
        boolean b = false;
        Log.d(TAG, "onTouchEvent1 return:"+b);
        return b;

    }

    @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

package com.touchstudy;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;

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, "onInterceptTouchEvent2 action:ACTION_DOWN");

                break;

            case MotionEvent.ACTION_MOVE:

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

                break;

            case MotionEvent.ACTION_UP:

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

                break;

            case MotionEvent.ACTION_CANCEL:

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

                break;

        }
        boolean b = false;
        Log.d(TAG, "onInterceptTouchEvent2 return:"+b);
        return b;

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        int action = ev.getAction();

        switch (action) {

            case MotionEvent.ACTION_DOWN:

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

                break;

            case MotionEvent.ACTION_MOVE:

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

                break;

            case MotionEvent.ACTION_UP:

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

                break;

            case MotionEvent.ACTION_CANCEL:

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

                break;

        }
       
        boolean b = false;
        Log.d(TAG, "onTouchEvent2 return:"+b);
        return b;
    }

}

onTouchEvent和onInterceptTouchEvent详细研究

    博客分类:
  • android开发
 

面试的时候曾被问过这两个方法的调用顺序,当时也只是知道onInterceptTouchEvent在前,具体的执行过程,相互的影响却不知道.今天写了一个小demo详细研究了一下这两个方法之间的关系.

首先上代码:

主activity:InterceptTouchStudyActivity

 

Java代码 复制代码 收藏代码
  1. package com.touchstudy;   
  2.   
  3. import android.app.Activity;   
  4. import android.os.Bundle;   
  5. import android.widget.TextView;   
  6.   
  7. public class InterceptTouchStudyActivity extends Activity {   
  8.   
  9.     TextView tv;   
  10.   
  11.     public void onCreate(Bundle savedInstanceState) {   
  12.   
  13.         super.onCreate(savedInstanceState);   
  14.   
  15.         setContentView(R.layout.main);   
  16.   
  17.     }   
  18.   
  19. }  

 布局文件main.xml

 

Java代码 复制代码 收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <com.touchstudy.LayoutView1 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.touchstudy.LayoutView2   
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="fill_parent"  
  10.         android:gravity="center"  
  11.         android:orientation="vertical" >   
  12.   
  13.         <com.touchstudy.MyTextView   
  14.             android:id="@+id/tv"  
  15.             android:layout_width="wrap_content"  
  16.             android:layout_height="wrap_content"  
  17.             android:background="#FFFFFF"  
  18.             android:text="AB"  
  19.             android:textColor="#0000FF"  
  20.             android:textSize="40sp"  
  21.             android:textStyle="bold" />   
  22.     </com.touchstudy.LayoutView2>   
  23.   
  24. </com.touchstudy.LayoutView1>  

 类LayoutView1

 

Java代码 复制代码 收藏代码
  1. package com.touchstudy;   
  2.   
  3. import android.content.Context;   
  4. import android.util.AttributeSet;   
  5. import android.util.Log;   
  6. import android.view.MotionEvent;   
  7. import android.widget.LinearLayout;   
  8.   
  9. public class LayoutView1 extends LinearLayout {   
  10.   
  11.     private final String TAG = "LayoutView1";   
  12.   
  13.     public LayoutView1(Context context, AttributeSet attrs) {   
  14.   
  15.         super(context, attrs);   
  16.   
  17.         Log.d(TAG, TAG);   
  18.   
  19.     }   
  20.   
  21.     @Override  
  22.     public boolean onInterceptTouchEvent(MotionEvent ev) {   
  23.   
  24.         int action = ev.getAction();   
  25.   
  26.         switch (action) {   
  27.   
  28.             case MotionEvent.ACTION_DOWN:   
  29.   
  30.                 Log.d(TAG, "onInterceptTouchEvent1 action:ACTION_DOWN");   
  31.   
  32.                 // return true;  
  33.   
  34.                 break;   
  35.   
  36.             case MotionEvent.ACTION_MOVE:   
  37.   
  38.                 Log.d(TAG, "onInterceptTouchEvent1 action:ACTION_MOVE");   
  39.   
  40.                 break;   
  41.   
  42.             case MotionEvent.ACTION_UP:   
  43.   
  44.                 Log.d(TAG, "onInterceptTouchEvent1 action:ACTION_UP");   
  45.   
  46.                 break;   
  47.   
  48.             case MotionEvent.ACTION_CANCEL:   
  49.   
  50.                 Log.d(TAG, "onInterceptTouchEvent1 action:ACTION_CANCEL");   
  51.   
  52.                 break;   
  53.   
  54.         }   
  55.         boolean b = false;   
  56.         Log.d(TAG, "onInterceptTouchEvent1 return:"+b);   
  57.         return b;   
  58.   
  59.     }   
  60.   
  61.     @Override  
  62.     public boolean onTouchEvent(MotionEvent ev) {   
  63.   
  64.         int action = ev.getAction();   
  65.   
  66.         switch (action) {   
  67.   
  68.             case MotionEvent.ACTION_DOWN:   
  69.   
  70.                 Log.d(TAG, "onTouchEvent1 action:ACTION_DOWN");   
  71.   
  72.                 break;   
  73.   
  74.             case MotionEvent.ACTION_MOVE:   
  75.   
  76.                 Log.d(TAG, "onTouchEvent1 action:ACTION_MOVE");   
  77.   
  78.                 break;   
  79.   
  80.             case MotionEvent.ACTION_UP:   
  81.   
  82.                 Log.d(TAG, "onTouchEvent1 action:ACTION_UP");   
  83.   
  84.                 break;   
  85.   
  86.             case MotionEvent.ACTION_CANCEL:   
  87.   
  88.                 Log.d(TAG, "onTouchEvent1 action:ACTION_CANCEL");   
  89.   
  90.                 break;   
  91.   
  92.         }   
  93.         boolean b = false;   
  94.         Log.d(TAG, "onTouchEvent1 return:"+b);   
  95.         return b;   
  96.   
  97.     }   
  98.   
  99.     @Override  
  100.     protected void onLayout(boolean changed, int l, int t, int r, int b) {   
  101.   
  102.         // TODO Auto-generated method stub  
  103.   
  104.         super.onLayout(changed, l, t, r, b);   
  105.   
  106.     }   
  107.   
  108.     @Override  
  109.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {   
  110.   
  111.         // TODO Auto-generated method stub  
  112.   
  113.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);   
  114.   
  115.     }   
  116.   
  117. }  

 类LayoutView2

 

package com.touchstudy;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;

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, "onInterceptTouchEvent2 action:ACTION_DOWN");

                break;

            case MotionEvent.ACTION_MOVE:

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

                break;

            case MotionEvent.ACTION_UP:

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

                break;

            case MotionEvent.ACTION_CANCEL:

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

                break;

        }
        boolean b = false;
        Log.d(TAG, "onInterceptTouchEvent2 return:"+b);
        return b;

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        int action = ev.getAction();

        switch (action) {

            case MotionEvent.ACTION_DOWN:

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

                break;

            case MotionEvent.ACTION_MOVE:

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

                break;

            case MotionEvent.ACTION_UP:

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

                break;

            case MotionEvent.ACTION_CANCEL:

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

                break;

        }
       
        boolean b = false;
        Log.d(TAG, "onTouchEvent2 return:"+b);
        return b;
    }

}

 类MyTextView

package com.touchstudy;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

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_TextView action:ACTION_DOWN");

                break;

            case MotionEvent.ACTION_MOVE:

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

                break;

            case MotionEvent.ACTION_UP:

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

                break;

            case MotionEvent.ACTION_CANCEL:

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

                break;

        }
        boolean b = false;
        Log.d(TAG, "onTouchEvent_TextView return:"+b);
        return b;

    }

    public void onClick(View v) {

        Log.d(TAG, "onClick");

    }

    public boolean onLongClick(View v) {

        Log.d(TAG, "onLongClick");

        return false;

    }

}

onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截,由于ViewGroup会包含若干childView,因此需要能够统一监控各种touch事件的机会,因此纯粹的不能包含子view的控件是没有这个方法的,如LinearLayout就有,TextView就没有。

关于返回值的问题,如果return true,那么表示该方法消费了此次事件,如果return false,那么表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理,需要说明的是,如果 onTouchEvent针对down事件返回了false,那么之后的move和up事件即使没有被拦截,也是接收不到的,或者说识别不了.

onInterceptTouchEvent()使用也很简单,如果在ViewGroup里覆写了该方法,那么就可以对各种touch事件加以拦截。但是如何拦截,是否所有的touch事件都需要拦截则是比较复杂的,touch事件在onInterceptTouchEvent()和onTouchEvent以及各个childView间的传递机制完全取决于onInterceptTouchEvent()和onTouchEvent()的返回值。并且,针对down事件处理的返回值直接影响到后续move和up事件的接收和传递。

总结一下,基本的规则是:

1. 对于一个事件,如果没有被任何view拦截的话(所有方法都返回false),全程的顺序是

LayoutView1->LayoutView2->MyTextView依次调用onInterceptTouchEvent()

然后MyTextView->LayoutView2->LayoutView1依次调用onTouchEvent()

2. onInterceptTouchEvent()只负责拦截不拦截,onTouchEvent()只负责处理不处理,两者只要返回true,该事件就停止向后传递.

3.如果该ViewGrouponInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGrouponTouchEvent()处理.

4.如果最终需要处理事件的viewonTouchEvent()返回了false,那么该事件将被传递至其上一层次的viewonTouchEvent()处理。

5.如果最终需要处理事件的viewonTouchEvent()返回了true,则上一层次的view收不到该事件,且后续事件将可以继续传递给该viewonTouchEvent()处理. 

 

下面开始在代码中试验.

1.onInterceptTouchEvent()处理事件均返回falseonTouchEvent()处理事件均返回true

 这是最常见的情况,onInterceptTouchEvent并没有做任何改变事件传递时序的操作,效果上和没有覆写该方法是一样的。可以看到,各种事件的传递本身是自底向上的,次序是:LayoutView1->LayoutView2->MyTextView。事件在MyTextView的OnTouch中被处理,停止了向父组件传递.
 

2.LayoutView1onInterceptTouchEvent()处理事件返回true,MyTextViewonTouchEvent()处理事件返回true

由于LayoutView1在拦截第一次事件时return true,所以后续的事件(包括第一次的down)将由LayoutView1本身处理,事件不再传递下去。

3.LayoutView1,LayoutView2的onInterceptTouchEvent()处理事件返回false,MyTextView的onTouchEvent()处理事件返回false,LayoutView2的onTouchEvent()处理事件返回true

由于MyTextViewonTouchEvent()return falsedown事件被传递给其父view,即LayoutView2onTouchEvent()方法处理,由于在LayoutView2onTouchEvent()return true,所以down事件传递并没有上传到LayoutView1注意,后续的moveup事件均被传递给LayoutView2onTouchEvent()处理,而没有传递给MyTextView
 
转载:http://androidbin.iteye.com/blog/1483511
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我赌博欠了10万怎么办 孩子见到生人不爱说话怎么办 18岁了个子矮小怎么办 1岁宝宝个子矮70怎么办 喋血街头2进监狱怎么办 360云盘收费了怎么办 头脑不清醒晕沉怎么办 一岁宝宝还不会走路怎么办 2岁宝宝受凉呕吐怎么办 3岁宝宝受凉呕吐怎么办 1岁宝宝受凉呕吐怎么办 3岁宝宝着凉呕吐怎么办 宝宝一进食就吐怎么办 宝宝吃什么都吐怎么办 一岁宝宝吃着了怎么办 宝宝吃了就吐怎么办 图书借阅证丢了怎么办 苹果6手机掌阅怎么办 厨房墙砖颜色深怎么办 炉石传说被盗号怎么办 炉石传说号忘了怎么办 手机丢失了微信怎么办 眼睛疼红血丝多怎么办 lol更新速度3kb怎么办 苹果6s玩游戏卡怎么办 微博手机号换了怎么办 微博字数超了怎么办 海外玩传奇很卡怎么办 再审期限超6个月怎么办 肠粉蒸出来太粘怎么办 微信订阅号没了怎么办 映美620k不进纸怎么办 属虎的带了貔貅怎么办 属龙的不能带金怎么办 这段时间运气不好怎么办 两年运气特别差怎么办 玩手机麻将老输怎么办 打四川麻将老输怎么办 网上打麻将老输怎么办 手机打麻将老输怎么办 近来打麻将老输怎么办