最近学习 Android,感觉Android事件传递机制很有意思,搞懂这个基础知识点是必须的,于是收集资料,做个Demo加深印象,记录之。

Demo比较简单,一个ViewGroup上放置一个按钮。

自定义VieGroup继承自LinearLayout:

package com.example.mydispatchtouchevent;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.View.OnClickListener;import android.view.View.OnTouchListener;import android.view.ViewGroup;import android.widget.LinearLayout;public class MyView extends LinearLayout implements OnClickListener,OnTouchListener{public MyView(Context context) {super(context);setOnClickListener(this);}@Overridepublic void onClick(View v) {Log.i("TAG","viewgroup_doClick");}@Overridepublic boolean onTouch(View v, MotionEvent event) {Log.i("TAG","viewgroup_onTouch="+event.getAction());return false;}@Overridepublic boolean onTouchEvent(MotionEvent event) {Log.i("TAG","viewgroup_onTouchEvent="+event.getAction());return super.onTouchEvent(event);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {Log.i("TAG","viewgroup_dispatchTouchEvent="+event.getAction());return super.dispatchTouchEvent(event);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {Log.i("TAG","viewgroup_onInterceptTouchEvent");return super.onInterceptTouchEvent(ev);}}

自定义Button:

package com.example.mydispatchtouchevent;import android.content.Context;import android.util.Log;import android.widget.Button;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;import android.view.View.OnClickListener;public class MyButton extends Button implements OnTouchListener,OnClickListener {public MyButton(Context context) {super(context);setOnTouchListener(this);setOnClickListener(this);this.setText("测试");}@Overridepublic boolean onTouch(View v, MotionEvent event) {Log.i("TAG", "button_onTouch=" + event.getAction());return false;}@Overridepublic boolean onTouchEvent(MotionEvent event) {Log.i("TAG", "button_onTouchEvent=" + event.getAction());return super.onTouchEvent(event);//return false;}@Overridepublic void onClick(View v) {Log.i("TAG", "button_doClick");}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {Log.i("TAG", "button_dispatchTouchEvent=" + event.getAction());return super.dispatchTouchEvent(event);}}

Activity:

package com.example.mydispatchtouchevent;import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.view.MotionEvent;import android.view.ViewGroup;import android.widget.Button;import android.widget.LinearLayout;public class MainActivity extends Activity {Button myBtn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ViewGroup viewGroup = new MyView(this);Button button = new MyButton(this);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);button.setLayoutParams(params);viewGroup.addView(button);setContentView(viewGroup);}@Overridepublic boolean onTouchEvent(MotionEvent event) {Log.i("TAG", "Activity_onTouchEvent=" + event.getAction() + " / "+ "event=" + event.hashCode());return super.onTouchEvent(event);}}

给自定义ViewGroup实现dispatchTouchEvent,onInterceptTouchEvent,onTouch,onTouchEvent,onClickButton实现dispatchTouchEvent,onTouch,onTouchEvent,onClick,Activity上实现onTouchEvent。

点击按钮,运行结果:

02-16 02:45:18.209: I/TAG(2535): viewgroup_dispatchTouchEvent=002-16 02:45:18.209: I/TAG(2535): viewgroup_onInterceptTouchEvent02-16 02:45:18.209: I/TAG(2535): button_dispatchTouchEvent=002-16 02:45:18.209: I/TAG(2535): button_onTouch=002-16 02:45:18.209: I/TAG(2535): button_onTouchEvent=002-16 02:45:18.313: I/TAG(2535): viewgroup_dispatchTouchEvent=102-16 02:45:18.313: I/TAG(2535): viewgroup_onInterceptTouchEvent02-16 02:45:18.313: I/TAG(2535): button_dispatchTouchEvent=102-16 02:45:18.313: I/TAG(2535): button_onTouch=102-16 02:45:18.313: I/TAG(2535): button_onTouchEvent=102-16 02:45:18.321: I/TAG(2535): button_doClick

顺序一目了然,viewgroup_dispatchTouchEvent先得到event,然后是viewgroup_onInterceptTouchEvent,接下来就把event转交给button,ACTION_DOWN和ACTION_UP各走一遍后,最后执行button_doClick。

这些方法的游戏规则是:如果返回true,event被消化了,不再传递;如果返回false,event交给下一位继续。在button_onTouchEvent中返回了true,事件传递就到此为止,其中button_doClick是在button_onTouchEvent中调用。

button_onTouchEvent修改为:

@Overridepublic boolean onTouchEvent(MotionEvent event) {Log.i("TAG", "button_onTouchEvent=" + event.getAction());//return super.onTouchEvent(event);return false;}

点击按钮:

02-16 03:02:38.213: I/TAG(2582): viewgroup_dispatchTouchEvent=002-16 03:02:38.213: I/TAG(2582): viewgroup_onInterceptTouchEvent02-16 03:02:38.213: I/TAG(2582): button_dispatchTouchEvent=002-16 03:02:38.213: I/TAG(2582): button_onTouch=002-16 03:02:38.213: I/TAG(2582): button_onTouchEvent=002-16 03:02:38.213: I/TAG(2582): viewgroup_onTouchEvent=002-16 03:02:38.317: I/TAG(2582): viewgroup_dispatchTouchEvent=102-16 03:02:38.317: I/TAG(2582): viewgroup_onTouchEvent=102-16 03:02:38.317: I/TAG(2582): viewgroup_doClick

这回button_onTouchEvent放水了,使得event继续往下“掉”,button_doClick不再执行,现在执行的是viewgroup_doClick。另外,发现button上只走了一遍ACTION_DOWN,ACTION_UP没它什么事,因为event已经不在button手中了(这么说比较形象)。

还没完,继续,viewgroup_onTouchEvent修改为

@Overridepublic boolean onTouchEvent(MotionEvent event) {Log.i("TAG","viewgroup_onTouchEvent="+event.getAction());//return super.onTouchEvent(event);return false;}

现在由viewgroup_onTouchEvent接着放水,点击按钮运行下结果:

02-16 03:18:56.737: I/TAG(2631): viewgroup_dispatchTouchEvent=002-16 03:18:56.737: I/TAG(2631): viewgroup_onInterceptTouchEvent02-16 03:18:56.737: I/TAG(2631): button_dispatchTouchEvent=002-16 03:18:56.737: I/TAG(2631): button_onTouch=002-16 03:18:56.737: I/TAG(2631): button_onTouchEvent=002-16 03:18:56.737: I/TAG(2631): viewgroup_onTouchEvent=002-16 03:18:56.737: I/TAG(2631): Activity_onTouchEvent=0 02-16 03:18:56.841: I/TAG(2631): Activity_onTouchEvent=1

现在终于轮到躺地板的Activity接到event了,过程参考上面,应该也比较好理解。

以下内容在stackOveflow找到,用来总结再合适不过了

How theActivityhandles touch:

  • Activity.dispatchTouchEvent()
    • Always first to be called
    • Sends event to root view attached to Window
    • onTouchEvent()
      • Called if no views consume the event
      • Always last to be called

How theViewhandles touch:

  • View.dispatchTouchEvent()
    • Sends event to listener first, if exists
      • View.OnTouchListener.onTouch()
    • If not consumed, processes the touch itself
      • View.onTouchEvent()

How aViewGrouphandles touch:

  • ViewGroup.dispatchTouchEvent()
    • onInterceptTouchEvent()
      • Check if it should supersede children
      • PassesACTION_CANCELto active child
      • Return true once, consumes all subsequent events
    • For each child view, in reverse order they were added
      • If touch is relevant (inside view),child.dispatchTouchEvent()
      • If not handled by previous, dispatch to next view
    • If no children handle event, listener gets a chance
      • OnTouchListener.onTouch()
    • If no listener, or not handled
      • onTouchEvent()
  • Intercepted events jump over child step

更多相关文章

  1. android动态修改drawable颜色及大小
  2. 查看Android的appPackage和Activity的多种方法
  3. Android之AppWidget的按钮事件开启Activity
  4. android BitmapFactory的内存溢出
  5. Android简单实现 高德地图的定位与显示,点击按钮切换地图图层
  6. 谁是最受欢迎的Linux发行版?
  7. Android欢迎页面WelcomeActivity实现
  8. Android(安卓)Studio提高效率插件---adb idea
  9. android jar包

随机推荐

  1. ubuntu android更新SDK长时间无法更新的
  2. Android(安卓)Shape 的使用
  3. Android(安卓)自定义标题栏的实例详解
  4. Android(安卓)Studio 中Copyright 设置
  5. 解决-Android: ListView.setSelection无
  6. Android第三方经典项目,框架,效果等的大集
  7. 异步访问----Android(安卓)AsyncTask 源
  8. Android(安卓)特别好用的框架 二,Spinner(
  9. Android获取短信session
  10. Android中获取图片尺寸大小两种方法