Android事件拦截机制
来源:互联网 发布:不用网络的搜题软件 编辑:程序博客网 时间:2024/06/05 03:12
触摸事件的类型
触摸事件就是捕获触摸屏幕后产生的事件,比如当点击一个按钮会产生—-按钮按下,这是事件一,如果不小心滑动了,这是事件二,当手指抬起的时候,这是事件三。安卓提供了MotionEvent类,封装了触摸事件的类型。- ACTION_DOWN:用户手指的按下操作,一个按下操作代表着一次触摸事件的开始。
- ACTION_MOVE:用户手指移动的操作,一般情况下,手指的轻微移动都会触发该方法。
- ACTION_UP:手指抬起操作,一次抬起代表着一次触摸事件和结束。
事件传递的三个方法
在事件传递具体实现之前,我们说下事件传递的三个方法事件分发方法
public boolean dispatchTouchEvent(MotionEvent event)
在安卓系统中,所有的触摸事件都是通过这个方法来分发的,在这个方法中,根据当前业务的实现逻辑,来决定是否消费这个事件还是将事件继续分发给子视图处理,方法返回值是true表示将当前事件消费掉,不再继续分发,当方法返回值是super.dispatchTouchEvent表示继续分发事件,当方法返回值是false,由父View消费事件。
事件拦截
public boolean onInterceptTouchEvent(MotionEvent event);
这个方法只有在ViewGroup及其子类中才存在,在View和Activity中是不存在的。返回true表示拦截这个事件,不继续分发给子视图,同时由自身的onTouchEvent方法进行消费,返回false或者super.onInterceptTouchEvent表示不对事件进行拦截,会继续将事件传递给子视图。
事件处理
public boolean onTouchEvent(MotionEvent event)
该方法返回true表示当前视图可以处理对应的事件,事件将不会向上传递给父视图中的onTouchEvent方法,返回值为false或者super.onTouchEvent(MotionEvent event)表示当前视图不处理这个事件,事件将会传递给父视图中的onTouchEvent方法进行处理。
在Android系统中
Activity:可以重写dispatchTouchEvent和onTouchEvent方法。ViewGroup:可以重写dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent三个方法。View:可以重写dispatchTouchEvent和onTouchEvent方法。
View的事件传递机制
上面已经说了View中可以重写dispatchTouchEvent和onTouchEvent方法,虽然ViewGroup的父类是View,但View中是没有onInterceptTouchEvent方法的。
我们将自定义一个MyView1,在事件处理相关的方法中打印Log,来观察事件处理的流程。public class MyView1 extends View{private static final String TAG = "eventdemo";public MyView1(Context context) { super(context);}public MyView1(Context context, @Nullable AttributeSet attrs) { super(context, attrs);}public MyView1(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {// Log.i(TAG, getClass().getSimpleName() + " dispatchTouchEvent"); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i(TAG, getClass().getSimpleName() + " dispatchTouchEvent ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i(TAG, getClass().getSimpleName() + " dispatchTouchEvent ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i(TAG, getClass().getSimpleName() + " dispatchTouchEvent ACTION_UP"); break; default: break; } return super.dispatchTouchEvent(event);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// Log.i(TAG, getClass().getSimpleName() + " onTouchEvent"); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i(TAG, getClass().getSimpleName() + " onTouchEvent ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i(TAG, getClass().getSimpleName() + " onTouchEvent ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i(TAG, getClass().getSimpleName() + " onTouchEvent ACTION_UP"); break; default: break; } return super.onTouchEvent(event);}}
同时在Activity中设置点击和触摸回调:
public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener {private static final String TAG = "eventdemo";private View myView1;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myView1 = findViewById(R.id.myview1); myView1.setOnClickListener(this); myView1.setOnTouchListener(this);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {// Log.i("eventdemo", getClass().getSimpleName() + " dispatchTouchEvent"); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: Log.i(TAG, getClass().getSimpleName() + " dispatchEvent ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i(TAG, getClass().getSimpleName() + " dispatchEvent ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i(TAG, getClass().getSimpleName() + " dispatchEvent ACTION_UP"); break; default: break; } return super.dispatchTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// Log.i("eventdemo", getClass().getSimpleName() + " onTouchEvent"); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i(TAG, getClass().getSimpleName() + " onTouchEvent ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i(TAG, getClass().getSimpleName() + " onTouchEvent ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i(TAG, getClass().getSimpleName() + " onTouchEvent ACTION_UP"); break; default: break; } return super.onTouchEvent(event);}@Overridepublic void onClick(View v) { Log.i(TAG, "myView1 onClick");}@Overridepublic boolean onTouch(View v, MotionEvent event) { Log.i(TAG, "myView1 onTouch"); return false;}}
run代码点击MyView1后打印:
ViewGroup的事件传递机制
我们将自定义一个MyGroupView1里面包含MyView1,在事件处理方法中打印Log,观察ViewGroup中的事件处理流程public class MyGroupView1 extends FrameLayout {private static final String TAG = "eventdemo";public MyGroupView1(@NonNull Context context) { super(context);}public MyGroupView1(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs);}public MyGroupView1(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {// Log.i(TAG, getClass().getSimpleName() + " dispatchTouchEvent"); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: Log.i(TAG, getClass().getSimpleName() + " dispatchTouchEvent ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i(TAG, getClass().getSimpleName() + " dispatchTouchEvent ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i(TAG, getClass().getSimpleName() + " dispatchTouchEvent ACTION_UP"); break; default: break; } return super.dispatchTouchEvent(ev);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: Log.i(TAG, getClass().getSimpleName() + " onInterceptTouchEvent ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i(TAG, getClass().getSimpleName() + " onInterceptTouchEvent ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i(TAG, getClass().getSimpleName() + " onInterceptTouchEvent ACTION_UP"); break; default: break; } return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i(TAG, getClass().getSimpleName() + " onTouchEvent ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i(TAG, getClass().getSimpleName() + " onTouchEvent ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.i(TAG, getClass().getSimpleName() + " onTouchEvent ACTION_UP"); break; default: break; } return super.onTouchEvent(event);}}
run代码点击MyView1后打印:
这里的onInterceptTouchEvent方法没有打印出来,是由于设置了onClickListener消费了事件导致的。从上面观察的Log看我们可以得出:
- 触摸事件的传递顺序是从Activity到ViewGroup,再由ViewGroup分发给子View的。
- ViewGroup会通过onInterceptTouchEvent方法对事件选择是否拦截,如果该方法返回true,则事件将会被拦截并由ViewGrup中的onTouchEvent处理。否则事件将会继续传递到子View中。
- 在子View中对事件进行消费后,ViewGroup将接收不到任何事件。
- Android 事件拦截机制
- Android 事件拦截机制
- android事件拦截机制
- Android事件拦截机制
- Android事件拦截机制
- Android事件拦截机制
- android 事件拦截机制总结
- Android事件拦截机制分析
- Android事件拦截机制分析
- Android事件拦截机制分析
- Android:Touch事件拦截机制
- Android事件拦截处理机制
- Android事件拦截机制分析
- Android 事件拦截机制、事件分发机制简单分析
- android事件拦截处理机制详解
- android事件拦截处理机制详解
- 【转】android事件拦截处理机制详解
- android事件拦截处理机制详解
- SpringMVC中使用Interceptor拦截器
- Android 开发之 Kotlin 初始篇
- 使用zxing生成二维码
- Java中的阻塞队列BlockingQueue
- UML学习笔记
- Android事件拦截机制
- 给IT新人的10个学习建议
- java 爬虫 网页解析(Jsoup)
- php八种数据类型
- Java多线程(三)- 线程同步
- bootstrap-datetimepicker 选择日期
- Git+Spring-boot+Docker+ Maven +Registry私有仓库 +jenkins 持续集成测试
- LeetCode Weekly Contest 33解题思路
- mysql -server-5.6 install master and slave on ubuntu 14.04server