View、ViewGroup事件(Touch事件)处理机制总结

Android中的事件

Touch事件,四种状态:

ACTION_DOWN ——> 表示按下了屏幕,一个事件必然从ACTION_DOWN开始ACTION_MOVE ——> 表示移动手势ACTION_UP ——> 表示离开屏幕ACTION_CANCEL ——> 表示取消手势,一般由程序产生,不会由用户产生

一个ACTION_DOWN, n个ACTION_MOVE,1个ACTION_UP,就构成了Android中众多的事件。

Android中的事件onClick, onScroll, onFling等等,都是由许多个Touch组成的。

一个原则,所有的touch事件都是从父容器开始向下传递的,呈U字形。

View事件处理机制核心代码

Android中诸如ImageView、textView、Button等控件都没有重写View的dispatchTouchEvent方法,所以View的事件处理机制对这些控件都有效。

View.java(基于android2.3.3):

public boolean dispatchTouchEvent(MotionEvent event) {//返回true,表示该View内部消化掉了所有事件。返回false,表示View内部只处理了ACTION_DOWN事件,事件继续传递,向上级View(ViewGroup)传递。…if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED&& li.mOnTouchListener.onTouch(this, event)) {//此处的onTouch方式就是回调的我们注册OnTouchListener时重写的onTouch()方法return true;}if (onTouchEvent(event)) {// onTouchEvent参考下面源码return true;}…}

public boolean onTouchEvent(MotionEvent event) {…// 当前onTouch的组件必须是可点击的比如Button,ImageButton等等,此处CLICKABLE为true,才会进入if方法,最后返回true。// 如果是ImageView、TexitView这些默认为不可点击的View,此处CLICKABLE为false,最后返回false。当然会有特殊情况,如果给这些View设置了onClick监听器,此处CLICKABLE也将为true,参考下面源码if (((viewFlags & CLICKABLE) == CLICKABLE ||(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {switch (event.getAction()) {case MotionEvent.ACTION_UP:…if (!post(mPerformClick)) {performClick();// 实际就是回调了我们注册的OnClickListener中重新的onClick()方法,源码下面源码}…break;case MotionEvent.ACTION_DOWN:…break;case MotionEvent.ACTION_CANCEL:…break;case MotionEvent.ACTION_MOVE:…break;}return true;}return false;}

public void setOnClickListener(OnClickListener l) {if (!isClickable()) {setClickable(true);}getListenerInfo().mOnClickListener = l;}

public boolean performClick() {…if (li != null && li.mOnClickListener != null) {…li.mOnClickListener.onClick(this);return true;}return false;}

总结:

只有我们注册OnTouchListener时重写的onTouch()方法中返回false ——> 执行onTouchEvent方法 ——> 导致onClick()回调方法执行

onTouch()方法返回true ——> onTouchEvent方法不执行 ——> 导致onClick()回调方法不会执行

ViewGroup事件处理机制核心代码

Android中诸如LinearLayout等的五大布局控件,都是继承自ViewGroup,,而ViewGroup本身是继承自View,所以ViewGroup的事件处理机制对这些控件都有效。

ViewGroup.java(基于android2.3.3):

@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {…if (action == MotionEvent.ACTION_DOWN) {if (mMotionTarget != null) {mMotionTarget = null;}//onInterceptTouchEvent返回false,说明向下传递//onInterceptTouchEvent返回true,说明拦截if (disallowIntercept || !onInterceptTouchEvent(ev)) {…// 伪代码如下://1,找到当前控件子控件//2,判断当前touch的点的坐标(x,y)在哪个子控件的矩形区域内//3,判断当前子控件是viewgroup的子类对象,还是view的子类对象//3.1 如果是viewgroup的子类: 调用其dispatchTouchEvent方法,上述操作再来一遍//3.2 view 尝试让当前view去处理这个事件(true,dispatchTouchEvent方法结束,并且返回truefalse,dispatchTouchEvent继续向下执行)…}}…target = mMotionTarget//target一定是nullif (target == null) {…//调用当前viewgroup的父View的处理事件的方法return super.dispatchTouchEvent(ev);}…}

public boolean onInterceptTouchEvent(MotionEvent ev) {return false;// 默认返回false}

总结:

1、dispatchTouchEvent作用:决定事件是否由onInterceptTouchEvent来拦截处理。

返回super.dispatchTouchEvent时,由onInterceptTouchEvent来决定事件的流向返回false时,会继续分发事件,自己内部只处理了ACTION_DOWN返回true时,不会继续分发事件,自己内部处理了所有事件(ACTION_DOWN,ACTION_MOVE,ACTION_UP)

2、onInterceptTouchEvent作用:拦截事件,用来决定事件是否传向子View

返回true时,拦截后交给自己的onTouchEvent处理返回false时,拦截后交给子View来处理

3、onTouchEvent作用:事件最终到达这个方法

返回true时,内部处理所有的事件,换句话说,后续事件将继续传递给该view的onTouchEvent()处理返回false时,事件会向上传递,由onToucEvent来接受,如果最上面View中的onTouchEvent也返回false的话,那么事件就会消失

综合案例分析

以下摘自:

既有美妙的风景,也会有称不上景只有风的地方。

View、ViewGroup事件(Touch事件)处理机制总结

相关文章:

你感兴趣的文章:

标签云: