Android事件拦截机制

一直对事件拦截不是很清楚,读Android群英传的笔记,记录下。

要了解事件拦截,首先要了解触摸事件,触摸事件是捕获触摸屏幕后发生的事件。按一下屏幕通常会有几个事件发生,当按下屏幕,这是事件1。滑动了一下,这是事件2。当手抬起,这是事件3。当重写onTouchEvent方法时,会给我们一个事件封装类MotionEvent。滑动,按下,对应不同的Action(如MotionEvent.ACTION_DOWN,MotionEvent.ACTION_UP),通过对Action的判断就可以实现不同的逻辑了。
咋一看触摸事件好像比较简单,但Android的View是树形结构的,一个View可能放在一个ViewGroup里面,而一个ViewGrop可能又放在另一个ViewGroup里面,可能会存在多层的嵌套结构,那么里面的触摸事件要给谁处理呢?这就要用到事件拦截了。

先附上代码。
MyViewGroupA.java

public class MyViewGroupA extends LinearLayout {
   public MyViewGroupA(Context context) {
       super(context);
   }
   public MyViewGroupA(Context context, AttributeSet attrs) {
       super(context, attrs);
   }
   public MyViewGroupA(Context context, AttributeSet attrs,
                       int defStyleAttr) {
       super(context, attrs, defStyleAttr);
   }
   @Override
   public boolean dispatchTouchEvent(MotionEvent ev) {
       Log.d("LOG", "ViewGroupA dispatchTouchEvent" + ev.getAction());
       return super.dispatchTouchEvent(ev);
   }
   @Override
   public boolean onInterceptTouchEvent(MotionEvent ev) {
       Log.d("LOG", "ViewGroupA onInterceptTouchEvent" + ev.getAction());
       return super.onInterceptTouchEvent(ev);
   }
   @Override
   public boolean onTouchEvent(MotionEvent event) {
       Log.d("LOG", "ViewGroupA onTouchEvent" + event.getAction());
       return super.onTouchEvent(event);
   }
}

MyViewGroupB.java

public class MyViewGroupB  extends LinearLayout {
   public MyViewGroupB(Context context) {
       super(context);
   }
   public MyViewGroupB(Context context, AttributeSet attrs) {
       super(context, attrs);
   }
   public MyViewGroupB(Context context, AttributeSet attrs,
                       int defStyleAttr) {
       super(context, attrs, defStyleAttr);
   }
   @Override
   public boolean dispatchTouchEvent(MotionEvent ev) {
       Log.d("LOG", "ViewGroupB dispatchTouchEvent" + ev.getAction());
       return super.dispatchTouchEvent(ev);
   }
   @Override
   public boolean onInterceptTouchEvent(MotionEvent ev) {
       Log.d("LOG", "ViewGroupB onInterceptTouchEvent" + ev.getAction());
       return super.onInterceptTouchEvent(ev);
   }
   @Override
   public boolean onTouchEvent(MotionEvent event) {
       Log.d("LOG", "ViewGroupB onTouchEvent" + event.getAction());
       return super.onTouchEvent(event);
   }
}

MyView.java

public class MyViewC extends View {
   public MyViewC(Context context) {
       super(context);
   }
   public MyViewC(Context context, AttributeSet attrs) {
       super(context, attrs);
   }
   public MyViewC(Context context, AttributeSet attrs,
                  int defStyleAttr) {
       super(context, attrs, defStyleAttr);
   }
   @Override
   public boolean onTouchEvent(MotionEvent event) {
       Log.d("LOG", "View onTouchEvent" + event.getAction());
       return super.onTouchEvent(event);
   }
   @Override
   public boolean dispatchTouchEvent(MotionEvent event) {
       Log.d("LOG", "View dispatchTouchEvent" + event.getAction());
       return super.dispatchTouchEvent(event);
   }
}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
   <com.example.administrator.testview.MyViewGroupA
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:background="@android:color/holo_blue_bright">
       <com.example.administrator.testview.MyViewGroupB
           android:layout_width="300dp"
           android:layout_height="300dp"
           android:background="@android:color/holo_green_dark">
           <com.example.administrator.testview.MyView
               android:layout_width="150dp"
               android:layout_height="150dp"
               android:background="@android:color/darker_gray" />
       </com.example.administrator.testview.MyViewGroupB>
   </com.example.administrator.testview.MyViewGroupA>
</RelativeLayout>

这里有2个ViewGroup,一个View,结构如下

Paste_Image.png

可以看到MyViewGroupA,在最外层,MyViewGroupB在中间,MyViewC在最底层。
ViewGroup分别重写了dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent
View重写了onTouchEvent,dispatchTouchEvent
可以看到ViewGroup比View多了一个方法,看名字是拦截的意思。

当我们点击MyViewC打印log如下


Paste_Image.png

可以看到事件的传递顺序是ViewGroupA -> ViewGroupB - > MyView
事件的处理顺序是MyView - > ViewGroupB - >ViewGroupA

Android对dispatchTouchEvent 的解释如下

/**
  * Pass the touch screen motion event down to the target view, or this
  * view if it is the target.
  *
  * @param event The motion event to be dispatched.
  * @return True if the event was handled by the view, false otherwise.
**/

dispatchTouchEvent 方法用来传递事件,返回True ,拦截,返回值false不拦截,继续传递。

onTouchEvent也类似,返回True处理,返回False交给上级处理。
可以知道无论是dispatchTouchEvent还是 onTouchEvent,如果返回True,表示这个事件被消费了、处理了不再往下传。

为了了解拦截过程,先忽略dispatchTouchEvent与onTouchEvent方法,简单修改ViewGroupB onInterceptTouchEvent为true,同样点击MyViewC,log如下

Paste_Image.png

可以看到ViewGroupB拦截后,果然MyView就没有事件继续传递了,事件被ViewGroupB自己完成。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容