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

本文深入解析了Android中onClick、onLongClick事件的触发顺序,以及它们与ACTION_DOWN及ACTION_UP事件的关系。通过详细分析View.java文件中的onTouchEvent方法,阐述了事件触发的逻辑流程,包括点击与长按事件的先后顺序。同时,解释了onTouch事件中down事件返回true与false的不同执行路径,以及如何影响onClick和onLongClick事件的触发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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上为500ms500ms后会触发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长按事件会一直自动执行下去)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值