Android:View事件分发机制

关于View事件分发机制的文章已经有很多了,推荐郭霖和鸿洋的两篇文章,

http://blog.csdn.net/guolin_blog/article/details/9097463

http://blog.csdn.net/lmj623565791/article/details/38960443

结合他们写的,自己简单总结一下,可能只适用个人。


流程

只要你触摸到了任何一个控件,就一定会调用该控件的dispatchTouchEvent方法,源码如下(最新的API源码已经不是这样了,但是分析依然可行)

public boolean dispatchTouchEvent(MotionEvent event) {
    ```
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
            mOnTouchListener.onTouch(this, event)) {
        return true;
    }
    return onTouchEvent(event);
}  

从这个方法可以看出,当控件setOnTouchListener后整个事件分发的流程如下:

View.dispatchEvent -> OnTouchListener.onTouch -> View.onTouchEvent

其中dispatchTouchEvent是当我们对View执行动作,如按下、移动、抬起等动作,系统调用的;onTouch就是程序员写的事件监听器setOnTouchListener(new OnTouchListener(){...})

当我们在onTouch方法里面返回true时,这时dispatchTouchEvent方法就会返回true而不会把事件分发到onTouchEvent了,而onClick方法、onLongClick方法正是在onTouchEvent方法里面调用的,所以只有在onTouch方法里面返回了false,才有可能触发onClickonLongClick方法。

观察onTouchEvent方法的源码(为了不占篇幅,直接从上面的文章看)我们可以知道:

①如果一个View是enable和clickable的时候,这个onTouchEvent一定会返回true,这个结论有什么用呢,当dispatchTouchEvent在进行事件分发的时候,只有这个方法返回true,才会触发下一个动作的事件。所以当onTouch方法返回false,事件会分发到onTouchEvent,如果View是enable和clickable的,必然会返回true,这样其他动作的事件才能继续触发dispatchTouchEvent。假如我们自己写一个自定义控件去继承Button,重写dispatchTouchEvent方法,将这个方法返回false时。我们点击这个Button,事件在执行完按下这个操作后就被消费了,当你抬起手指时系统也不会调用再dispatchTouchEvent了!

②当处在MotionEvent.ACTION_UP时,如果系统判定之前处在MotionEvent.ACTION_DOWN执行过长按操作,即调用了下面这个performLongClick方法(其实内部就是回调OnLongClickListeneronLongClick方法),并且返回的是false,才能触发onClick。否则onLongClick方法返回truemHasPerformedLongPress就变为true,就无法执行

performClick方法了。

if (performLongClick()) {
                    mHasPerformedLongPress = true;
                }  
if (!mHasPerformedLongPress) {
                            // This is a tap, so remove the longpress check
                            removeLongPressCallback();  

                            // Only perform take click actions if we were in the pressed state
                            if (!focusTaken) {
                                // Use a Runnable and post this rather than calling
                                // performClick directly. This lets other visual state
                                // of the view update before click actions start.
                                if (mPerformClick == null) {
                                    mPerformClick = new PerformClick();
                                }
                                if (!post(mPerformClick)) {
                                    performClick();
                                }
                            }
                        }  

小结

当你操作一个控件时,不管是按下、移动、抬起,在事件中途未被消费的情况下系统会按照View.dispatchEvent -> OnTouchListener.onTouch -> View.onTouchEvent分发下去。

如,按下控件时产生一个MotionEvent.ACTION_DOWN事件,系统首先将事件分发到dispatchTouchEvent,然后将事件分发到程序员写的onTouch方法,

  1. 如果这个onTouch方法返回了truedispatchTouchEvent则返回true,事件不会传递到onTouchEvent
  2. 如果onTouch方法返回了falsedispatchTouchEvent将会调用onTouchEvent方法,在这个方法内处理各种逻辑。
    1. 当处理ACTION_DOWN时经过系统判断此次为长按操作,将回调程序员写的长按方法,如果程序员写的onLongClick方法返回true,将使得长按标志位为true
    2. 当处理ACTION_UP时如果长按标志位为false时,才会回调onClick方法,默认情况下长按标志位为false
  3. 如果dispatchTouchEvent方法返回false,则无法触发其他动作的事件,这里要分清事件是否会触发以及事件是否会分发。

执行完按下动作后执行抬起动作,系统产生MotionEvent.ACTION_UP事件,则又按上述事件分发流程走一遍。

时间: 2024-08-01 22:47:58

Android:View事件分发机制的相关文章

Android View 事件分发机制源码详解(View篇)

前言 在Android View 事件分发机制源码详解(ViewGroup篇)一文中,主要对ViewGroup#dispatchTouchEvent的源码做了相应的解析,其中说到在ViewGroup把事件传递给子View的时候,会调用子View的dispatchTouchEvent,这时分两种情况,如果子View也是一个ViewGroup那么再执行同样的流程继续把事件分发下去,即调用ViewGroup#dispatchTouchEvent:如果子View只是单纯的一个View,那么调用的是Vie

Android View 事件分发机制 源码解析 (上)

一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个MyButton继承Button,然后把跟事件传播有关的方法进行复写,然后添加上日志~ MyButton [java] view plain copy package com.example.zhy_event03; import android.content.Context; import andr

Android View事件分发机制

最近在开发中遇到view滑动冲突的问题,由于一开始就知道这个问题与view事件分发有关,之后在网上看了几篇关于事件分发的资料后,开发中遇到的问题很快便得到解决. 在这里总结一下我对view事件分发的理解. 首先,看下事件分发流程图: Button事件演示 在对view的事件分发机制进行分析前,我们可以通过一个demo看看Button的事件处理的流程. 在布局文件中添加一个button控件,然后在代码中实现Button的setOnClickListener和setOnTouchListener方法

Android View 事件分发机制梳理

View初探 一直以来对View的事件分发机制很晕,今天就在这里梳理一下 MyView 首先继承View类,自定义一个MyView.并在初始化时打印View类是否可点击,这里从View点击事件分发的角度出发,所以不考虑绘制,测量相关方法的实现. public class MyView extends View { String TAG = "Activity"; public MyView(Context context) { super(context); init(); } pub

Atitit View事件分发机制

1. Atitit View事件分发机制 1. Atitit View事件分发机制1 1.1. 三个关键方法 dispatchTouchEvent onInterceptTouchEvent onTouchEvent1 1.1.1. public boolean dispatchTouchEvent(MotionEvent ev)1 1.1.2. public boolean onInterceptTouchEvent(MotionEvent ev)1 1.1.3. public boolean

Android6.0 ViewGroup/View 事件分发机制详解

之前自认为对于Android的事件分发机制还算比较了解,直到前一阵偶然跟人探讨该问题,才发现自己以前的理解有误,惭愧之余遂决定研习源码,彻底弄明白Android的事件分发机制,好了废话少说,直接开干. 首先,我们对Android中的touch事件做一下总结,主要分为以下几类: 1.Action_Down  用户手指触碰到屏幕的那一刻,会触发该事件: 2.Action_Move   在触碰到屏幕之后,手指开始在屏幕上滑动,会触发Action_Move事件: 3.Action_Up       在用

从源码角度带你分析 Android View 事件分发 dispatchTouchEvent,onTouch,onTouchEvent,onClick逻辑顺序过程(一)

关于Android View 事件分发过程的文章网络上可以搜到一把大,这里贴一篇代码性的文章,作者也是个牛人:Android事件分发机制完全解析,带你从源码的角度彻底理解(上). 虽然讲的很好,但是看完之后还是感觉有那么点一知半解,于是自己花了点时间从源码研究android 触摸事件分发流程,以下内容仅仅个人理解,如有差错希望指出. 我们先从一个例子看起,先重写一个MyButton 继承Button,代码如下: public class MyButton extends Button { pub

android 从源码分析view事件分发机制

一直对View的事件分发机制不太明白,在项目开发中也遇到过,在网上也找到一些解决问题方法,但是其原理并不太了解,现在辞职了有时间,今天写写View的事件分发,结合android源码一起来学习下,如果讲的不对,往指出一起学习提高,言归正传. 新建一个android项目,里面只有一个activity,有一个button,我们给Button设置setOnClickListener(),setOnTouchListener(),通过log看看结果: btnClick.setOnClickListener

Android View框架总结(七)View事件分发机制

请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52282833 View布局告一段落,从本篇开始View事件相关分析,今天分析的是View的事件分发机制(PS:本篇文章中源码均是android 6.0,请知晓) View 事件的分发机制 dispatchTouchEvent onInterceptTouchEvent onTouchEvent 案例 事件通常重要的有如下三种: MotionEvent.ACTION_