您的位置:首页 > 移动开发 > Android开发

Android:ViewGroup事件分发机制

2015-06-14 21:03 781 查看
关于ViewGroup事件分发机制的文章已经有很多了,推荐郭霖和鸿洋的两篇文章,

/article/1562149.html

/article/1336233.html

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

流程

在上一篇文章中讲到,当你操作一个控件时,不管是按下、移动、抬起,在事件中途未被消费的情况下系统会按照
View.dispatchTouchEvent -> OnTouchListener.onTouch -> View.onTouchEvent
分发下去。事实上,事件最先分发到的是
ViewGroup
dispatchTouchEvent
、然后分发到
onInterceptTouchEvent
方法,而第二个方法顾名思义就是用来拦截消费事件的。代码如下,默认就是不拦截。

[code]public boolean onInterceptTouchEvent(MotionEvent ev) {  
    return false;  
}


接下来看一下
ViewGroup.dispatchTouchEvent
方法,源码比较长为了不占篇幅,可以直接在上面的文章看。观察源码可以发现,当
按下
控件时事件会分发到
onInterceptTouchEvent
方法中,而默认这个方法是返回false,然后系统通过坐标的计算得出当前按的控件是否是ViewGroup里面的子View,如果是,将事件分发给这个子View,也就是按照
View.dispatchTouchEvent -> OnTouchListener.onTouch -> View.onTouchEvent
**,并且将这个子View赋给target记录下来,方便后面控件移动、抬起操作的识别。如果不是,则会有如下代码

[code]if (target == null) {  
        ev.setLocation(xf, yf);  
        if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {  
            ev.setAction(MotionEvent.ACTION_CANCEL);  
            mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;  
        }  
        return super.dispatchTouchEvent(ev);  
    }


可以看到如果点击的不是子View,则会把事件分发到
super.dispatchTouchEvent
方法,而ViewGroup的父类正是View,所以可以这么理解,点击一个控件时,先在
ViewGruop.dispatchTouchEvent
里面判断点击的是不是子View,是则按照View的事件分发机制分发下去,否则把ViewGroup本身作为一个View,按照View的事件分发机制分发下去。而常见的ViewGroup无非就是一些布局还有AdapterView等。

小结

如果ViewGroup可以找到子View,就将事件分发给子View,否则自己作为一个View分发事件。

通过重写
ViewGroup.onInterceptTouchEvent
方法可以实现对不同动作的事件的拦截,由ViewGroup自身处理事件。

分析两篇文章,我们一般都不需要重写ViewGroup和View的
dispatchTouchEvent
方法和
View.onTouchEvent
方法,程序员需要关心的是
ViewGroup.onInterceptTouchEvent
onTouch
,前者是实现ViewGroup对子View事件的拦截,后者是实现View分发流程时
onTouch
方法对
onTouchEvent
方法的拦截,而
onTouchEvent
则是实现判断
onLongClick
onClick
等动作的逻辑的。

ViewGroup.onInterceptTouchEvent
默认返回
false
,则点击到子View时会把事件分发给子View,
onTouch
返回
false
或者不存在
OnTouchListener
时,则会把事件分发到
onTouchEvent
onLongClick
返回
false
或者不存在
OnLongClickListener
时,事件才有可能传递给
onClick
方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: