android 触摸监听重写_Android触摸事件传递机制

简单梳理一下Android触摸事件传递机制的知识点。

一、View与ViewGroup的关系

View和ViewGroup二者的继承关系如下图所示:

View是Android中最基本的一种UI组件,它是所有控件类的基类。View类的作用是可以在屏幕上绘制一块矩形区域,并能响应这块区域的各种事件(如触摸事件、点击事件等)。我们平时使用的各种控件其实都是继承自View类,在View的基础上又添加了一些特有的功能。比如TextView可以用于显示文本,进一步还能拓展(extends)为可编辑的文本控件——EditText类或者可点击的文本控件——Button类。

ViewGroup也是继承自View类,但它是一种非常特殊的View,因为它可以作为一个容器来放置其他的控件或布局。我们常用的各种布局Layout类以及ListView、ScrollView等都是继承自ViewGroup。

在讨论Android触摸事件传递机制时,我们这里说的View特指除了ViewGroup以外的View控件,也就是无法作为容器的最小UI单位。

二、Android UI层次结构

Android UI层次结构图和类图如下图所示:

Activity是Android应用程序的门面和载体,它代表一个完整的用户界面。Activity提供了一个窗口来绘制各种视图,即PhoneWindow类。该类继承自顶层窗口类Window,并且包含一个DecorView类对象。DecorView继承自FrameLayout(帧布局),所以本质上是一个ViewGroup,而且是当前活动所放置的全部View的根视图(RootView)。当我们创建一个活动时,在活动的onCreate()方法中调用setContentView(R.layout.layout_name)方法就是为该活动的ContentView部分指定布局内容从而完成GUI的渲染。

三、事件的类型

事件主要分为触摸事件和点击事件。

1、触摸事件:对应的是MotionEvent类,主要有以下三种类型:

ACTION_DOWN:表示用户手指按下的动作,标志着触摸事件的开始。

ACTION_UP:表示用户手指离开屏幕的动作,标志着触摸事件的结束。

ACTION_MOVE:表示用户手指移动的动作。当用户手指按下屏幕后,在松开之前,只要移动的距离超过了一定的阈值即判定为ACTION_MOVE动作。实际上,即使是手指非常   轻微的移动也会被系统监测到从而判定为ACTION_MOVE动作。

ps:用户触摸屏幕操作由ACTION_DOWN事件开始,结束于ACTION_UP事件,可以有0次或多次ACTION_MOVE事件。

2、点击事件:用户手指按下→停留若干时间(可长可短)→用户手指松开,这一完整的过程视为一次点击事件。可以看出,触摸事件先于点击事件执行。

四、触摸事件传递机制

该机制主要包含三个角色、三个阶段和三个方法。

1、三个角色分别为:Activity、View、ViewGroup。

2、三个阶段分别为:分发(dispatch)、拦截(intercept)和消费(consume)。

3、三个方法的方法原型分别为:

①public boolean dispatchTouchEvent(MotionEvent e)……对应于分发事件

②public boolean onInterceptTouchEvent(MotionEvent e)……对应于拦截事件

③public boolean onTouchEvent(MotionEvent e)……对应于消费事件(即处理事件)

4、解释:

由前面的Android UI层次结构分析可以看出来,一个Activity包含多层视图:先是窗口(PhoneWindow),接着是根视图(即DecorView),然后是具体的ContentView;ContentView视图部分又是各种布局和控件的嵌套组合。那么,当用户做出了触摸动作时,触摸事件应当由哪一个View或者哪一个ViewGroup负责处理呢?这就是触摸事件传递机制要解决的问题。为了方便,下面会用视图这一词代替View或ViewGroup对象。

①在Android系统中,所有触摸事件必须都由dispatchTouchEvent()方法判断是否进行分发。分发事件相当于“传递事件”的一个过程,分发事件的目的就是为了找到正确的视图来处理这个触摸事件。而处理事件的过程就是所谓的消费阶段,调用的方法是onTouchEvent()。如果确定要继续分发事件,向什么地方分发呢?如果是ViewGroup,则是向自己的子视图进行分发;如果是View,向子视图进行分发本质上其实就是分发给自身。如果dispatchTouchEvent()方法返回true,则表示事件由当前视图直接进行消费(处理),不再继续分发;否则,向子视图进行分发。

②除了分发和消费,还有一个拦截操作。须注意的是:只有ViewGroup可以拦截触摸事件,Activity和View只能分发事件和消费事件。这一点其实非常好理解:因为View没有子视图可言,所以不存在拦截的操作;而ViewGroup具有子视图,选择性地进行拦截事件是有意义的。ViewGroup可以调用onInterceptTouchEvent()方法来判断是否拦截该触摸事件。如果该方法返回true,表示拦截该事件不再分发给子视图;否则,表示不拦截事件继续分发给子视图。须注意,ViewGroup类默认是不拦截任何触摸事件的,如果有需要可以重写其onInterceptTouchEvent()方法进行选择性地拦截。

③一旦确定由某个视图负责处理(即消费)触摸事件ACTION_DOWN,那么后续的ACTION_MOVE和ACTION_UP等触摸事件也会同样被该视图捕获。在消费事件阶段,该视图会调用onTouchEvent()方法。如果该方法返回true,那么表示事件被成功消费;如果返回false,那么意味着当前视图没有能力消费该触摸事件,事件会抛给上层的视图调用其onTouchEvent()方法进行处理。

5、触摸事件传递过程:

考虑最一般的情况,即触摸事件ACTION_DOWN由某个View消费掉的情况。事件传递过程分成两步,整个过程都严格遵循上述的分发、拦截和消费的原理。如下图所示:

①第一步:先由Activity传递到ViewGroup,具体地讲就是Activity→PhoneWindow→DecorView(根视图)。

②第二步:由根视图DecorView通过一层层的ViewGroup传递到某个子View,由该View负责消费该事件以及后续的事件。

至于其他的情况,比如该View捕获到事件后无法消费抛给上层视图或者某个ViewGroup捕获到事件,则参考下图:

五、something more

除了分发、拦截和消费这三个方法外,还可以在活动中为View类设置监听器接口:

监听触摸事件:setOnTouchListener(),须重写接口的onTouch()方法。

监听点击事件:setOnClickListener(),须重写接口的onClick()方法。

监听长按事件:setOnLongClickListener(),须重写接口的onLongClick()方法

观察View类的源码,有以下结论:

①View的onTouch()方法会先于onTouchEvent()方法执行,并且当前仅当onTouch()方法返回false时,才会执行onTouchEvent()。

②只有当onTouchEvent()方法得到调用,并且触摸事件是ACTION_UP时,onClick()方法才会被调用。这一点逻辑上也非常容易理解,因为当用户手指按下屏幕,只有当他手指离开屏幕触发事件ACTION_UP后才算是一个点击事件。也就是说,当一个View确定捕获触摸事件时,onTouch()方法会介于分发方法和消费方法之间执行,并且只有当其返回false时,后续的消费方法onTouchEvent()才能执行。而只有onTouchEvent()方法成功执行返回true,才能表示触摸事件被正确处理,如果是ACTION_UP被正确处理,那么就会调用onClick()方法。

③这三个监听方法的执行顺序是:onTouch()方法→onLongClick()→onClick() 原因:当用户按下手指后,先执行触摸监听方法;如果用户按下时间超过一个阈值还没有松手,会执行长按监听方法;如果用户最后松开手指,最后执行点击监听方法。并且这三个方法是后者依赖于前者的返回值!只有onClick()返回false,onLongClick()才能执行;只有onLongClick()返回false,onClick()才能执行。

.............................................................................................................................................................over

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值