Android触摸屏事件派发机制详解与源码分析一(View篇)(1)

final int actionMasked = event.getActionMasked();

if (actionMasked == MotionEvent.ACTION_DOWN) {

// Defensive cleanup for new gesture

stopNestedScroll();

}

if (onFilterTouchEventForSecurity(event)) {

//noinspection SimplifiableIfStatement

ListenerInfo li = mListenerInfo;

if (li != null && li.mOnTouchListener != null

&& (mViewFlags & ENABLED_MASK) == ENABLED

&& li.mOnTouchListener.onTouch(this, event)) {

result = true;

}

if (!result && onTouchEvent(event)) {

result = true;

}

}

if (!result && mInputEventConsistencyVerifier != null) {

mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);

}

// Clean up after nested scrolls if this is the end of a gesture;

// also cancel it if we tried an ACTION_DOWN but we didn’t want the rest

// of the gesture.

if (actionMasked == MotionEvent.ACTION_UP ||

actionMasked == MotionEvent.ACTION_CANCEL ||

(actionMasked == MotionEvent.ACTION_DOWN && !result)) {

stopNestedScroll();

}

return result;

}

dispatchTouchEvent的代码有点长,咱们看重点就可以。前面都是设置一些标记和处理input与手势等传递,到24行的if (onFilterTouchEventForSecurity(event))语句判断当前View是否没被遮住等,接着26行定义ListenerInfo局部变量,ListenerInfo是View的静态内部类,用来定义一堆关于View的XXXListener等方法;接着if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event))语句就是重点,首先li对象自然不会为null,li.mOnTouchListener呢?你会发现ListenerInfo的mOnTouchListener成员是在哪儿赋值的呢?怎么确认他是不是null呢?通过在View类里搜索可以看到:

/**

  • Register a callback to be invoked when a touch event is sent to this view.

  • @param l the touch listener to attach to this view

*/

public void setOnTouchListener(OnTouchListener l) {

getListenerInfo().mOnTouchListener = l;

}

li.mOnTouchListener是不是null取决于控件(View)是否设置setOnTouchListener监听,在上面的实例中我们是设置过Button的setOnTouchListener方法的,所以也不为null;接着通过位与运算确定控件(View)是不是ENABLED 的,默认控件都是ENABLED 的;接着判断onTouch的返回值是不是true。通过如上判断之后如果都为true则设置默认为false的result为true,那么接下来的if (!result && onTouchEvent(event))就不会执行,最终dispatchTouchEvent也会返回true。而如果if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event))语句有一个为false则if (!result && onTouchEvent(event))就会执行,如果onTouchEvent(event)返回false则dispatchTouchEvent返回false,否则返回true。

这下再看前面的实例部分明白了吧?控件触摸就会调运dispatchTouchEvent方法,而在dispatchTouchEvent中先执行的是onTouch方法,所以验证了实例结论总结中的onTouch优先于onClick执行道理。如果控件是ENABLE且在onTouch方法里返回了true则dispatchTouchEvent方法也返回true,不会再继续往下执行;反之,onTouch返回false则会继续向下执行onTouchEvent方法,且dispatchTouchEvent的返回值与onTouchEvent返回值相同。

所以依据这个结论和上面实例打印结果你指定已经大胆猜测认为onClick一定与onTouchEvent有关系?是不是呢?先告诉你,是的。下面我们会分析。

3-2-1 总结结论

在View的触摸屏传递机制中通过分析dispatchTouchEvent方法源码我们会得出如下基本结论:

  1. 触摸控件(View)首先执行dispatchTouchEvent方法。

  2. 在dispatchTouchEvent方法中先执行onTouch方法,后执行onClick方法(onClick方法在onTouchEvent中执行,下面会分析)。

  3. 如果控件(View)的onTouch返回false或者mOnTouchListener为null(控件没有设置setOnTouchListener方法)或者控件不是enable的情况下会调运onTouchEvent,dispatchTouchEvent返回值与onTouchEvent返回一样。

  4. 如果控件不是enable的设置了onTouch方法也不会执行,只能通过重写控件的onTouchEvent方法处理(上面已经处理分析了),dispatchTouchEvent返回值与onTouchEvent返回一样。

  5. 如果控

  • 18
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值