Button的ontouch,onclick,onLongclick的执行顺序

Android中,onClickonLongClick的触发是和ACTION_DOWNACTION_UP相关的,在时序上,如果我们在一个View中同时覆写了onClickonLongClickonTouchEvent的话,onTouchEvent是最先捕捉到ACTION_DOWNACTION_UP事件的,其次才可能触发onClick或者onLongClick。主要的逻辑在View.java中的onTouchEvent方法中实现的:

<span style="font-size:14px;"><span style="color:#333333;">case MotionEvent.ACTION_DOWN:
    mPrivateFlags |= PRESSED;
    refreshDrawableState();
    if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
        </span><span style="color:#ff0000;"> postCheckForLongClick(); </span><span style="color:#333333;">
    }
    break;</span></span>
<span style="font-size:14px;"><span style="color: rgb(51, 51, 51);">
case MotionEvent.ACTION_UP:
    if ((mPrivateFlags & PRESSED) != 0) {
         boolean focusTaken = false;
         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
               focusTaken = requestFocus();
         }
    if (!mHasPerformedLongPress) {
       if (mPendingCheckForLongPress != null) {
             removeCallbacks(mPendingCheckForLongPress);
       }
       if (!focusTaken) {
             </span><span style="color:#ff0000;"> performClick();</span><span style="color:#333333;">
       }
    }
    …
    break;</span></span>
可以看到, Click 的触发是在系统捕捉到 ACTION_UP 后发生并由 performClick() 执行的, performClick 里会调用先前注册的监听器的 onClick() 方法:

<span style="font-size:14px;">public boolean performClick() {
    …
    if (mOnClickListener != null) {
        playSoundEffect(SoundEffectConstants.CLICK);
        <span style="color:#3366ff;">mOnClickListener.onClick(this);</span>
        return true;
    }</span>
<span style="font-size:14px;">        return false;
}</span>

ongClick 的触发则是从 ACTION_DOWN 开始,由 postCheckForLongClick() 方法完成:

<span style="color:#333333;">private void postCheckForLongClick() {
     mHasPerformedLongPress = false;
     if (mPendingCheckForLongPress == null) {
         mPendingCheckForLongPress = new CheckForLongPress();
     }
     mPendingCheckForLongPress.rememberWindowAttachCount();
    </span><span style="color:#3366ff;"> postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout());</span><span style="color:#333333;">
}</span>

可以看到,在 ACTION_DOWN 事件被捕捉后,系统会开始触发一个 postDelayed 操作, delay 的时间在 Eclair2.1 上为 500ms 500ms 后会触发 CheckForLongPress 线程的执行:

<span style="font-size:14px;"><span style="color:#333333;">class CheckForLongPress implements Runnable {
…
        public void run() {
            if (isPressed() && (mParent != null)
                    && mOriginalWindowAttachCount == mWindowAttachCount) {
                if (</span><span style="color:#3366ff;">performLongClick()</span><span style="color:#333333;">) {
                    mHasPerformedLongPress = true;
                }
            }
        }
…
}</span></span>
如果各种条件都满足,那么在 CheckForLongPress 中执行 performLongClick() ,在这个方法中将调用 onLongClick()

<span style="color:#333333;">public boolean performLongClick() {
      …
      if (mOnLongClickListener != null) {
          </span><span style="color:#3366ff;">handled = mOnLongClickListener.onLongClick(View.this);</span><span style="color:#333333;">
      }
      …
}</span>


Button的onTouch,onClick,onLongClick事件发生先后顺序和关联:

注意: onTouch事件中:down事件返回值标记此次事件是否为点击事件,返回false说明是点击事件,返回true不记为点击事件;up事件标记此次事件结束时间,也就是判断是否为长按。

一. onTouch返回false,执行顺序

1.如果长按:down-->onLongClick-->up-->onClick

2.如果点击:down-->up-->onClick

二. onTouch返回true,执行顺序:down-->up,不会触发onclick以及onLongClick

三. onTouch:down返回true,up返回false执行顺序结果同二:down-->up,不会触发onclick以及onLongClick
       机制分析:   onTouch事件中:down返回true,系统将不把本次事件记录为点击事件,也就不会触发onClick或者onLongClick事件了。因此尽管当up的时候返回false,系统也不会继续触发onClick事件了。

四.onTouch:down返回false,up返回true执行顺序:

1.如果长按:down-->onLongClick-->up

2.如果点击:down-->up------>(达到一定时间后自动触发onLongClick)

      机制分析:  onTouch事件中:down返回false,说明此次事件为点击事件,而up返回了true,说明此次事件一直没有结束,也就是一直长按下去了,达到长按临界时间后,自然触发长按事件,而onClick事件没有触发到


结论:1.ontouch的down事件返回true一定不会触发onclick事件

2.ontouch的down事件返回false,up事件返回ture一定会触发onLongClick事件,并且不会触发onclick事件(因为up返回true长按事件会一直自动执行下去)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值