我不是在问如何处理触摸事件,而是在幕后发生了什么?如果有几个嵌套的小部件,他们看到的事件是什么顺序?开发人员是否可以控制它?理想情况下,我想要一个关于这个主题的文件.
Sur*_*gch 65
我们来看一个视觉示例.
当触摸事件发生时,首先向每个人通知事件,从活动开始并一直到顶部的视图.然后每个人都有机会处理事件,从顶部视图开始,一直回到活动.因此,活动是第一个听到它并且最后有机会处理它.
如果某个ViewGroup想要立即处理触摸事件(并且没有让其他任何人有机会),那么它就可以返回true
它onInterceptTouchEvent()
.活动没有,onInterceptTouchEvent()
但您可以覆盖dispatchTouchEvent()
以执行相同的操作.
如果View(或ViewGroup)具有OnTouchListener
,则触摸事件由处理OnTouchListener.onTouch()
.否则它由处理onTouchEvent()
.如果任何触摸事件onTouchEvent()
返回true
,则处理停止.没有其他人有机会获得它.
上图使事情比实际更简单.例如,在Activity和ViewGroup A(根布局)之间还有Window和DecorView.我把它们排除在上面,因为我们通常不必与它们互动.但是,我会将它们包含在下面.以下描述遵循通过源代码的触摸事件.您可以单击链接以查看实际的源代码.
(更新:源代码已更新,因此行号现已关闭,但单击链接仍会使您找到正确的文件.只需搜索方法名称.)
dispatchTouchEvent()
被通知触摸事件.触摸事件作为a传入MotionEvent
,其中包含x,y坐标,时间,事件类型和其他信息.superDispatchTouchEvent()
.Window
是一个抽象类.实际的实现是PhoneWindow
.superDispatchTouchEvent()
.DecorView
它处理状态栏,导航栏,内容区等.它实际上只是一个FrameLayout
子类,它本身就是一个子类ViewGroup
.RelativeLayout
,a LinearLayout
还是a ConstraintLayout
,它们都是子类ViewGroup
.并且ViewGroup会收到有关触摸事件的通知dispatchTouchEvent()
.这是上图中的ViewGroup A.ViewGroup
会通知任何孩子有触摸事件,包括任何ViewGroup
儿童.这是我上图中的ViewGroup B.ViewGroup
都可以通过返回来短路通知过程.true
onInterceptTouchEvent()
ViewGroup
剪切通知短,通知行的自然结束是View dispatchTouchEvent()
的调用.OnTouchListener
,那么它第一次有机会处理触摸事件onTouch()
.否则,View onTouchEvent()
会处理它.View
.虽然,我没有表明这上面的图中,一个ViewGroup
是View
子类,所以一切我已描述OnTouchListener.onTouch()
和onTouchEvent()
也适用于ViewGroups.onTouchEvent()
.我什么时候需要覆盖dispatchTouchEvent()
?
如果要在任何视图有机会之前捕获触摸事件,请在活动中覆盖它.对于ViewGroup(包括根视图),然后只需覆盖onInterceptTouchEvent()
和onTouchEvent()
.
我什么时候需要覆盖onInterceptTouchEvent()
?
如果您只想窥探即将进入的触摸通知,您可以在此处进行并返回false
.
但是,重写此方法的主要目的是让ViewGroup处理特定类型的触摸事件,同时让子处理另一种类型.例如,a ScrollView
执行此操作以处理滚动,同时让其子项处理类似Button按钮的操作.相反,如果子视图不想让其父级窃取其触摸事件,则可以调用requestDisallowTouchIntercept()
.
什么是触摸事件类型?
主要是
ACTION_DOWN
- 这是触摸事件的开始.你应该总是返回true
的ACTION_DOWN
事件onTouchEvent
,如果你要处理的触摸事件.否则,您将无法再获得任何活动.ACTION_MOVE
- 当您在屏幕上移动手指时,此事件会不断触发.ACTION_UP
- 这是触摸事件的最后一个事件.亚军是ACTION_CANCEL
.如果树上的ViewGroup决定拦截触摸事件,则会调用此方法.
您可以在此处查看其他类型的MotionEvent .由于Android是多点触控的,因此当其他手指("指针")触摸屏幕时也会触发事件.
Poi*_*ull 24
从活动角度来看:
Touch事件首先传递给Activity.dispatchTouchEvent.这是你可以先抓住它们的地方.
在这里,他们被调度到Window,在那里他们遍历View层次结构,其顺序是最后绘制的Widgets(在其他小部件之上)有机会首先在View.onTouchEvent中处理触摸.如果某些View在onTouchEvent中返回true,则遍历停止并且其他视图不会接收触摸事件.
最后,如果没有View消耗触摸,它将被传递给Activity.onTouchEvent.
这完全是你的控制.而且你所看到的东西在其他东西之上绘制是合乎逻辑的,有机会在它下面绘制的东西之前处理触摸事件.
我已经准备了一个高级图来说明一个简单的流程。
dispatchTouchEvent()
- Activity
, ViewGroup
,View
onInterceptTouchEvent()
—— ViewGroup
onTouch()
- ViewGroup
,View
。使用setOnTouchListener()
onTouchEvent()
- Activity
, ViewGroup
,View
归档时间: |
|
查看次数: |
10518 次 |
最近记录: |