Android的Touch事件分发机制,看完这个就够了
2015-08-03 17:11
615 查看
最近在整理 关于Android的Touch事件的分发机制,首先Touch事件的方法包括三种:dispatchTouchEvent(MotionEvent event) , onInterceptTouchEvent(MotionEvent ev) , onTouchEvent(MotionEvent event) ,下面是这三个方法在界面中的调用映射表:
Ps:这里的View 若只是Button或者其他不包含子控件的View是不包含OnInterceptTouchEvent方法的。
下面进行事件分发的详细解析:
☟ : 表示向下子类分发事件
☞ : 表示由自己来处理事件
下面 我们通过代码来验证一下我们上面的理论:
首先定义两个子布局:
tauchButton:
父控件touchLinearlayout:
activity的layout布局:
Activity1:
首先我们先看看都使用super的方法时是神马结果;
case1 : 所有的返回值都调用super方法
这里我们可以看出,首先由Activity的dispatchTouchEvent方法,想下分发事件,由于是Activity,没有OnIterceptTouchEvent因此是分发给子控件的dispatchTouchEvent方法,当到TouchEventFather分发事件的时候,就是分发给了自己的OnIntercepterTouchEvent ; 这时候调用的依然是super的方法,根据上面的表格显示,默认不拦截,就把事件分发给了下一个控件的dispatchTouchEvent , 最终由于都没有消耗该事件,于是事件会由子控件返回给当前的Acticity,然后释放掉。
下面我们随机测试一下其他的情况:
case2 : 父控件的onTouchEvent的返回值设置为true
截图可以看出,当运行到TouchEventFather的OnTouchEvent的时候,就把事件给消耗掉了,就不会走Activity的OntouchEvent的方法了;
case3:tauchButton的dispatchTouchEvent的返回值是false
截图可以发现,当运行到tauchButton的dispatchEvent方法,返回false时,事件不再向下分发,而是将事件传递给上层的View的OntouchEvent方法;
剩下的 都经过实践的出,这里不再一一列举。
当然到这里,我们基本搞懂了View的事件分发,不过我们似乎还忘了一点事情,那就是View的监听事件:setOnTouchListener 和 setOnClickListener.到这里的时候 我突然想到如果给button加一个监听事件会怎么样。
下面将Activity该成如下形式:
我们再次运行会发现如图所示。当事件分发到TouchEventChilds的OntouchEvent的时候,被touchListener事件拦截,并且消耗掉事件。
如果我们把setOnTouchListener的返回值设置为false;
这时我们可以发现,事件会被一直传递下去,直到传递给setOnClickListener事件。如果没有监听Onclick事件的时候:
事件会按原路返回到Activity然后释放掉;
那么我们现在可以发现:
触摸事件传递顺序:dispatchTouchEvent–>>onTouch–>>onTouchEvent–>>onClick。而且是当OnTouchEvent的手势ACTION_UP结束的时候才会调用Onclick方法。到这里我们基本对Touch的事件有了一定的了解了。
Ps:本文主要参考下面的blog:[ /article/4917556.html ]
Touch事件的方法 | 方法介绍 | View | ViewGroup | Activity |
---|---|---|---|---|
dispatchTouchEvent | 事件的分发 | yes | yes | yes |
onInterceptTouchEvent | 事件的拦截 | yes | yes | no |
onTouchEvent | 事件的响应 | yes | yes | yes |
下面进行事件分发的详细解析:
Touch事件的方法\返回值 | 解析 | true | false | super() |
---|---|---|---|---|
dispatchTouchEvent | 每次的Touch都会由Activity的dispatchTouchEvent向下层的View或ViewGroup进行事件分发 | ☞当前的控件自己处理事件 | 1、若该View是Activity或者是button等不含子控件的View,则将事件分发给自己处理 ☞ ; 2、否则传递给上层的Activity或者父控件的OnTouchEvent方法 ☝ | ☟ 下发给Activity的子控件或View自身的OnIntercepterTouchEvent |
onInterceptTouchEvent | 是否拦截事件 | ☞ 当前View的OnTouchEvent | ☟ 子控件的dispatch | ☞ |
onTouchEvent | 事件的响应 | ☞ 当前View | ☝ 父控件的TouchEvent | ☝ |
解释:
☝ : 表示向上父类传递事件☟ : 表示向下子类分发事件
☞ : 表示由自己来处理事件
下面 我们通过代码来验证一下我们上面的理论:
首先定义两个子布局:
tauchButton:
public class tauchButton extends LinearLayout { public tauchButton(Context context) { super(context); } public tauchButton(Context context, AttributeSet attrs) { super(context, attrs); } public tauchButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("zgy", "TouchEventChilds | onTouchEvent --> " + TouchEventUtil.getTouchAction(event.getAction())); return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i("zgy", "TouchEventChilds | dispatchTouchEvent --> " + TouchEventUtil.getTouchAction(event.getAction())); return super.dispatchTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i("zgy", "TouchEventChilds | onInterceptTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction())); return super.onInterceptTouchEvent(ev); } }
父控件touchLinearlayout:
public class touchLinearlayout extends LinearLayout { public touchLinearlayout(Context context) { super(context); } public touchLinearlayout(Context context, AttributeSet attrs) { super(context, attrs); } public touchLinearlayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { Log.e("zgy", "TouchEventFather | onTouchEvent --> " + TouchEventUtil.getTouchAction(event.getAction())); return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.e("zgy", "TouchEventFather | dispatchTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction())); return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.e("zgy", "TouchEventFather | onInterceptTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction())); return super.onInterceptTouchEvent(ev); } }
activity的layout布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <com.example.lk.helloworld.view.touchLinearlayout android:layout_width="match_parent" android:layout_height="400dp" android:background="@color/bg_discount" android:layout_gravity="center"> <com.example.lk.helloworld.view.tauchButton android:id="@+id/buttonChild" android:layout_width="200dp" android:layout_height="200dp" android:text="button" android:background="@color/bg_blue_light" android:layout_gravity="center" android:layout_marginLeft="20dp" /> </com.example.lk.helloworld.view.touchLinearlayout> </LinearLayout>
Activity1:
package com.example.lk.helloworld; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import com.example.lk.helloworld.utils.TouchEventUtil; /** * */ public class Activity1 extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity1_layout); } @Override public boolean onTouchEvent(MotionEvent event) { Log.w("zgy", "TouchEventActivity | onTouchEvent --> " + TouchEventUtil.getTouchAction(event.getAction())); return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.w("zgy", "TouchEventActivity | dispatchTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction())); return super.dispatchTouchEvent(ev); } }
首先我们先看看都使用super的方法时是神马结果;
case1 : 所有的返回值都调用super方法
这里我们可以看出,首先由Activity的dispatchTouchEvent方法,想下分发事件,由于是Activity,没有OnIterceptTouchEvent因此是分发给子控件的dispatchTouchEvent方法,当到TouchEventFather分发事件的时候,就是分发给了自己的OnIntercepterTouchEvent ; 这时候调用的依然是super的方法,根据上面的表格显示,默认不拦截,就把事件分发给了下一个控件的dispatchTouchEvent , 最终由于都没有消耗该事件,于是事件会由子控件返回给当前的Acticity,然后释放掉。
下面我们随机测试一下其他的情况:
case2 : 父控件的onTouchEvent的返回值设置为true
截图可以看出,当运行到TouchEventFather的OnTouchEvent的时候,就把事件给消耗掉了,就不会走Activity的OntouchEvent的方法了;
case3:tauchButton的dispatchTouchEvent的返回值是false
截图可以发现,当运行到tauchButton的dispatchEvent方法,返回false时,事件不再向下分发,而是将事件传递给上层的View的OntouchEvent方法;
剩下的 都经过实践的出,这里不再一一列举。
当然到这里,我们基本搞懂了View的事件分发,不过我们似乎还忘了一点事情,那就是View的监听事件:setOnTouchListener 和 setOnClickListener.到这里的时候 我突然想到如果给button加一个监听事件会怎么样。
下面将Activity该成如下形式:
package com.example.lk.helloworld; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.View; import com.example.lk.helloworld.utils.TouchEventUtil; import com.example.lk.helloworld.view.tauchButton; /** * */ public class Activity1 extends Activity { private tauchButton buttonChild; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity1_layout); buttonChild = (tauchButton)findViewById(R.id.buttonChild); buttonChild.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Log.e("Activity1.this","touchListener 事件触发"); return true; } }); buttonChild.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e("Activity1.this", "clickListener 事件触发"); } }); } @Override public boolean onTouchEvent(MotionEvent event) { Log.w("zgy", "TouchEventActivity | onTouchEvent --> " + TouchEventUtil.getTouchAction(event.getAction())); return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.w("zgy", "TouchEventActivity | dispatchTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction())); return super.dispatchTouchEvent(ev); } }
我们再次运行会发现如图所示。当事件分发到TouchEventChilds的OntouchEvent的时候,被touchListener事件拦截,并且消耗掉事件。
如果我们把setOnTouchListener的返回值设置为false;
这时我们可以发现,事件会被一直传递下去,直到传递给setOnClickListener事件。如果没有监听Onclick事件的时候:
事件会按原路返回到Activity然后释放掉;
那么我们现在可以发现:
触摸事件传递顺序:dispatchTouchEvent–>>onTouch–>>onTouchEvent–>>onClick。而且是当OnTouchEvent的手势ACTION_UP结束的时候才会调用Onclick方法。到这里我们基本对Touch的事件有了一定的了解了。
Ps:本文主要参考下面的blog:[ /article/4917556.html ]
相关文章推荐
- Android中View属性大全
- 【Android应用开发技术:媒体开发】录像
- Android ListView的setEmptyView方法的使用
- Android Studio中如何引用图片资源
- android 遍历本地联系人
- Android之MVC模式
- 【Android】开机自启动Service
- 【Android】Service学习之本地服务
- 【Android】Service 生命周期
- Android自定义控件:如何使用自定义的XML属性
- 如何更快捷的设置Android Studio和Eclipse的快捷键一样和代码提示
- Android4.0 Launcher拖拽原理分析(1)
- Android ANR-Thermal condition
- Android屏幕保护KeyguardManager相关内容学习
- Android 适配横屏
- android中import出错,且该包切实存在的时候
- 【Android基础】AsyncTask学习——如何取消掉AsyncTask
- Android studio gradle 多渠道打包
- Android 自定义ListView控件,滑动删除
- 使用Android studio分析内存泄露