关于Android触摸事件TouchEvent的传递及截取,研究心得。
来源:互联网 发布:系统网络协议栈有损坏 编辑:程序博客网 时间:2024/06/04 18:57
之前一直经常使用Touch的相关操作,但是对其中的具体细节一直没有详细的研究一下,今天研究了一下,感觉思路有点清晰了很多,再次记录一下。
其中关于Android触摸事件相关的函数有:dispatchTouchEvent() | onInterceptTouchEvent()|onTouchEvent()
由函数的名字也大概能够知道具体的作用是什么了:dispatchTouchEvent()负责触摸事件的分发,onInterceptTouchEvent()决定事件是不是在当前的View下拦截,onTouchEvent()负责触摸事件的处理消化。
先说一下传递的机制和顺序吧。
我们建立一个这样的场景,就是在一个Activity中有一个View,名叫:Layout_out_0,在Layout_out_0中还有嵌套在里面的一个View,叫Layout_inner_0,相信大家也能够想象是个什么东西吧。
当你触摸屏幕的时候,首先产生事件的顺序为:DOWN——>MOVE(这个事件的产生和你触摸时的触摸时间的长度有关,如果时间极短,就不会产生,如果一直按住,就会一直产生MOVE)——>UP(手指抬起的时候);当然这个顺序是固定的,事件的处理也是一个传递消化完毕之后,才开始第二个事件的传递消化,很固定。
好进入重点,DOWN事件产生首先经由Activity的dispatchTouchEvent(),在Activity中是没有方法onInterceptTouchEvent()方法的,也就无法使产生的事件被拦截了,接着进入等级仅次于Activity的容器组件View中,也是经由dispatchTouchEvent()(不过我在测试程序中尝试把该函数的返回值super.dispatchTouchEvent()修改为false或者是true结果发现导致事件无法正常的分发,所以不建议大家重写该回调函数),在经过onInterceptTouchEvent()决定是不是要拦截该事件,如果onInterceptTouchEvent()返回true则表示要拦截,那么事件就不会再继续往子控件传递了(否则继续重复上面的步骤,再次进入子控件的dispatchTouchEvent()——>onInterceptTouchEvent()),直接进入当前组件的onTouchEvent()当中进行事件的处理,如果onTouchEvent()返回true,则表示事件在此被消化,不会往父控件传递了,如果返回的是false表示事件还尚未消化,继续返回到父控件的onTouchEvent()(注意,是直接进入父控件的onTouchEvent()当中)
通过上面的描述不知道大家有没有高明白其中的逻辑呢。
那我在形象的说一下啊吧,简单画了一个思维导图,当不进行任何的消息拦截,即在某一层上的onInterceptTouchEvent()返回true,也不进行任何消息的消化,即在某一层上的onTouchEvent()返回true,的这种情况下,消息的传递是这样的:
如果在某一层上的onInterceptToucEvent()中进行了拦截,也就是返回了true,那么消息就不会继续往下层子控件走了。
比如说如果在Layout_out_0中进行了拦截,那么消息就会进入Layout_out_0中的onTouchEvent()中,进行消息的处理,如果Layout_out_0中的onTouchEvent()返回的是false,那么意思就是并没有把消息消化,那么会返回上层父类容器中的onTouchEvent()也就是Activtiy中的;如果Layout_out_0中的onTouchEvent()返回的true,表示的就是在这儿已经把消息消化掉了,就不会再继续向父类的onTouchEvent进行传递了。
好了,大家懂了吗?
说完了DOWN事件,那么在说一下MOVE和UP,这两个事件是根据DOWN的消化地点决定,比如说消化地点在Layout_out_0中,那么MOVE和UP的路线是Activity的dispatchTouchEvent()——>Layout_out_0的dispatchTouchEvent()——>Layout_out_0的onInterceptTouchEvent()——>Layout_out_0的onTouchEvent()——>结束,无论这边的onInterceptTouchEvent()拦截还是不拦截都是这样的(都不会继续往子控件Layout_inner_0中传递了),这样做感觉逻辑上确实很有说服力,就是在哪儿消化的就只到传递到哪儿,能够节约很多的资源和时间。
然后如果有人想亲自测试一下这个过程,我把我的代码贴上,仅供参考。
布局文件activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" tools:context="${relativePackage}.${activityClass}" > <com.example.toucheventtest.Layout_out_0 android:id="@+id/out0" android:layout_width="300dp" android:layout_height="300dp" android:background="#ff0000ff" > <com.example.toucheventtest.Layout_inner_0 android:id="@+id/inner0" android:layout_width="200dp" android:layout_height="200dp" android:background="#ffff0000" > </com.example.toucheventtest.Layout_inner_0> </com.example.toucheventtest.Layout_out_0></RelativeLayout>
Layout_out_0.java:
package com.example.toucheventtest;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.RelativeLayout;public class Layout_out_0 extends RelativeLayout {public static final String TAG = "T";public Layout_out_0(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {Log.e(TAG, "Layout_out_0+onInterceptTouchEvent:" + ev.getAction());return false;}@Overridepublic boolean onTouchEvent(MotionEvent ev) {Log.e(TAG, "Layout_out_0+onTouchEvent:" + Common.getAction(ev));return false;}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {Log.e(TAG,"layout_out_0+dispatchTouchEvent:"+Common.getAction(ev));return super.dispatchTouchEvent(ev);}}
Layout_inner_0.java:
package com.example.toucheventtest;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.RelativeLayout;public class Layout_inner_0 extends RelativeLayout {public static final String TAG = "T";public Layout_inner_0(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {Log.e(TAG,"layout_inner_0+onInterceptTouchEvent:" + Common.getAction(ev));return true;}@Overridepublic boolean onTouchEvent(MotionEvent ev) {Log.e(TAG, "layout_inner_0+onTouchEvent:" + Common.getAction(ev));return true;}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {Log.e(TAG, "layout_inner_0+dispatchTouchEvent:" + ev.getAction());return super.dispatchTouchEvent(ev);}}
Common类:
package com.example.toucheventtest;import android.view.MotionEvent;public class Common {public static String getAction(MotionEvent event) {String actionname = "none";switch (event.getAction()) {case MotionEvent.ACTION_DOWN:actionname = "down";break;case MotionEvent.ACTION_MOVE:actionname = "move";break;case MotionEvent.ACTION_UP:actionname = "up";break;default:break;}return actionname;}}
MainActivity.java:
package com.example.toucheventtest;import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.MotionEvent;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubLog.e("T", "MainActivity+onTouchEvent:" + Common.getAction(event));return true;}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {Log.e("T", "MainActivity+dispatchTouchEvent:" + Common.getAction(event));return super.dispatchTouchEvent(event);}}
差不多结束了,剩下的就是根据不同的场景去改变函数中的返回值了,这样的话就能对TouchEvent进行控制了。
- 关于Android触摸事件TouchEvent的传递及截取,研究心得。
- android各种触摸事件的处理,touchEvent
- android TouchEvent事件传递
- Android touchEvent事件传递
- TouchEvent事件的传递
- 关于Android触摸事件传递
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- zendskeletion Internal Server Error The server encountered an internal error or misconfiguration and
- Oracle数据库监听非常慢,基本hang住故障处理
- 140723暑期培训
- c++四种类型转换关键字(转)
- vmstat命令
- 关于Android触摸事件TouchEvent的传递及截取,研究心得。
- 黑马程序员_java反射
- Cs学习笔记-配置环境使包含checked关键字
- UVA 10385 - Duathlon(三分法)
- digu.com/board/detail/twypnlhrt6ydB
- hdoj3374 最小表示法+KMP求周期
- Q_PROPERTY
- poj_2234
- Oracle数据库中出现ORA-01157: 无法标识/锁定数据文件