android 点击事件拦截,Android 事件分发拦截(基础篇)
原标题:Android 事件分发拦截(基础篇)Android 事件分发拦截(基础篇)。android的事件分发,浅一点大家都懂,深一点我自己就hold不住了。写这篇文章是希望能帮助刚接触android的朋友对android事件分发有个简单的了解,也是对自己学习的一个归纳总结吧。三个类ActivityViewGroupView三个方法boolean dispatchTouchEvent(Motion
原标题:Android 事件分发拦截(基础篇)
Android 事件分发拦截(基础篇)。
android的事件分发,浅一点大家都懂,深一点我自己就hold不住了。写这篇文章是希望能帮助刚接触android的朋友对android事件分发有个简单的了解,也是对自己学习的一个归纳总结吧。
三个类
Activity
ViewGroup
View
三个方法
boolean dispatchTouchEvent(MotionEvent event)
boolean onInterceptTouchEvent(MotionEvent ev)
boolean onTouchEvent(MotionEvent event)
先说三个类
系统捕获到用户的触摸事件后,会进行一系列逻辑处理(具体需看源码),然后把这个触摸事件交给Activity,Activity会把这个触摸事件交给与之绑定的layout的最外层ViewGroup,如果ViewGroup中有子视图(可能是ViewGroup,也可能是View),看用户触摸到的是哪个子视图,然后将这个触摸事件继续传递,直到没有子视图为止(一般子视图是View的时候就不会再传递了)(这里有个前提,ViewGroup重新onInterceptTouchEvent(MotionEvent ev)的返回值不能为rue,稍后会说明原因)
再来说下三个方法
首先是dispatchTouchEvent(MotionEvent ev) 方法,从方法名称可知这个方法是用来处理事件分发逻辑的,系统捕获到用户的触摸事件后,最终会调用Activity的dispatchTouchEvent(MotionEvent ev) 方法来传递触摸事件,参数MotionEvent 就是对触摸事件的封装,可以获取到触摸事件的类型(ACTION_DOWN:用户手按下屏幕、ACTION_MOVE:用户触摸屏幕并在屏幕上滑动、ACTION_DOWN:用户手抬起离开屏幕),用户的触摸区域的坐标等等(详情请自行查阅相关内容)
其次是onInterceptTouchEvent(MotionEvent ev) 方法,从方法名称可知这个方法是用来拦截事件的,返回值为boolean类型,true代表本类要拦截此事件,此事件不再往子类传递;false代表不拦截,此事件继续往子类传递。Activity和View没有此方法。Activity是第一个接收到触摸事件的非系统类(因为是自己继承的Activity),它是不能进行事件拦截的,必须要要把事件传递给真正意义上的视图。而View因为没有子类,事件到了这里本身就不会再进行传递,所有没有拦截的必要。
最后是onTouchEvent(MotionEvent event) 方法,这里是真正意义上处理触摸事件的地方。Activity、ViewGroup、View都可以重新此方法,执行各自的触摸事件对应的逻辑。
介绍完了三个类三个方法后,开始上代码案例了;
界面、代码及结果展示
重写了MainActivity的dispatchTouchEvent()、onTouchEvent()方法
自定义TestTouchEventViewGroupParent的onTouchEvent()、dispatchTouchEvent()、onInterceptTouchEvent()三个函数
以及TestTouchEventView的onTouchEvent()、dispatchTouchEvent()方法
然后用手触摸蓝底的TestTouchEventView,看下log
简单解释一下log,首先Activity的dispatchTouchEvent()被系统调用,Activity找到他的子布局也就是TestTouchEventViewGroup,调用他的dispatchTouchEvent()方法,TestTouchEventViewGroup在dispatchTouchEvent()方法内部会调用onInterceptTouchEvent()来检测是否设置过事件拦截,系统默认为false(不拦截),检测完之后会将事件继续传递给子视图即TestTouchEventView并调用它的dispatchTouchEvent()方法,因为TestTouchEventView是最小的视图单元,事件不用再进行传递,在dispatchTouchEvent()方法中调用onTouchEvent,开始进行事件处理。onTouchEvent()有个boolean的返回值,true代表消耗了此次事件,它的父布局及父布局以上的ouTouchEvent()都不会再被执行,返回false代表此次事件未消耗,此次事件可以交由当前布局的副布局进行事件处理。(super.onTouchEvent(event) 默认返回false,切记)
当我们想处理一个控件的滑动事件时,我们需要重写onTouchEvent()方法,并在里面对事件类型做对应的处理,一轮事件默认的顺序是ACTION_DOWN、ACTION_MOVE.....ACTION_MOVE、ACTION_UP,当用户触摸屏幕产生事件(首先是ACTION_DOWN),系统捕获到会调用Activity的dispatchTouchEvent方法传递给Activity,Activity发现是ACTION_DOWN默认会继续往子类传递,传至TestTouchEventViewGroup,TestTouchEventViewGroup不进行拦截,传至TestTouchEventView。上图log中,TestTouchEventView没有消耗此次事件,事件处理权回到了TestTouchEventViewGroup手上,然后调用自己onTouchEvent()方法进行事件处理,如果还是没有消耗掉此次事件,事件的处理权最终回到了Activity手上,Activity在处理自己的onTouchEvent()方法,如果Activity在onTouchEvent()的事件处理中,也没有消耗掉此次事件(ACTION_DOWN),请注意!!!当用户产生第二个行为过来时,比如ACTION_MOVE,系统还是会捕获事件调用Activity的dispatchTouchEvent()方法进行事件分发,但这里会去检测之前ACTION_DOWN事件是否被消耗掉,在哪个视图内被消耗掉的,下一次的事件派发到那个视图就打止了,不会再往子视图传递事件。如果事件直到回到Activity时都还没被消耗掉,次轮事件不会再进行派发,每次到Activity就为止了。这也就是有的朋友去监听触摸事件,只能监听到ACTION_DOWN,后面的事件再也监听不到的原因了,因为除ACTION_DOWN的事件早在之前就被拦截了,根本没传下来。
更多内容请关注:计算机毕业设计 http://www.shuangyulin.com返回搜狐,查看更多
责任编辑:
更多推荐
所有评论(0)