按键分析--APP部分-- OnLongClickListener事件处理流程

5.4         OnLongClickListener事件处理流程

 

 

5.4.1         OnLongClickListener注册和使用

其注册和使用方法和OnClickListener相似,在activity里实现接口,

public class Launcher extends Activity

        implements View.OnLongClickListener,

 

view设置监听器,

        mWorkspace.setOnLongClickListener(this);

 

view基类里调用performLongClick,执行onLongClick()

    public boolean performLongClick() {

        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);

 

        boolean handled = false;

        ListenerInfo li = mListenerInfo;

        if (li != null && li.mOnLongClickListener != null) {

            handled = li.mOnLongClickListener.onLongClick(View.this);

        }

        if (!handled) {

            handled = showContextMenu();

        }

        if (handled) {

            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);

        }

        return handled;

    }

 

 

5.4.2         OnClickListener栈分析

栈的调用过程和OnClickListener也类似,用异步的方式调用到activity的onLongClick方法,

Launcher.onLongClick(View) line: 5169     

CellLayout(View).performLongClick() line: 5244      

View$CheckForLongPress.run() line: 21138

Handler.handleCallback(Message) line: 739 

ViewRootImpl$ViewRootHandler(Handler).dispatchMessage(Message) line: 95      

Looper.loop() line: 148 

ActivityThread.main(String[]) line: 5524    

Method.invoke(Object, Object...) line: not available [native method]

ZygoteInit$MethodAndArgsCaller.run() line: 752      

ZygoteInit.main(String[]) line: 642     

 

 

所以我们看一下消息是如何post出来的即可。

 

Android的触摸消息中,已经实现了三种监测,它们分别是

1)pre-pressed:对应的语义是用户轻触(tap)了屏幕

2)pressed:对应的语义是用户点击(press)了屏幕

3)long pressed:对应的语义是用户长按(long press)了屏幕

下图是触摸消息随时间变化的时间轴示意图:

其中,t0和t1定义在ViewConfiguration类中,标识了tap和longpress的超时时间,定义如下:

private static final int TAP_TIMEOUT = 100;

private static final int DEFAULT_LONG_PRESS_TIMEOUT = 500;

 

在早期版本中,在View类的OnTouchEvent函数中,当View监测到ACTION_DOWN事件时,首先发送一个延迟为t0的异步消息处理tap,在Android6.0中则不使用这种机制了。

 

长按的调用栈:

onTouchEvent --checkForLongClick –post

—CheckForLongPress--run --performLongClick-- .mOnLongClickListener.onLongClick

 

如前分析,在onTouchEvent的MotionEvent.ACTION_DOWN,执行checkForLongClick,延时post一个长按消息出去。

                case MotionEvent.ACTION_DOWN:

                    mHasPerformedLongPress = false;

                    // Walk up the hierarchy to determine if we're inside a scrolling container.

                    boolean isInScrollingContainer = isInScrollingContainer();

 

                    // For views inside a scrolling container, delay the pressed feedback for

                    // a short period in case this is a scroll.

                    if (isInScrollingContainer) {

                        mPrivateFlags |= PFLAG_PREPRESSED;

                        if (mPendingCheckForTap == null) {

                            mPendingCheckForTap = new CheckForTap();

                        }

                        mPendingCheckForTap.x = event.getX();

                        mPendingCheckForTap.y = event.getY();

                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());

                    } else {

                        // Not inside a scrolling container, so show the feedback right away

                        setPressed(true, x, y);

                        checkForLongClick(0);

                    }

                    break;

 

 

在MotionEvent.ACTION_UP及MOVE\CANCEL中, 会清除长按的异步消息,设置相关的变量和按键状态,这样,如果这些事件产生在长按超期前,长按就不起作用;在长按超期后,长按有效,并完成了按键的周期流程。所以按键处理的逻辑就是这样的。

                 removeLongPressCallback();

 

                 setPressed(false);

 

 onClick和onLongClick能同时发生吗?

要理解Android对事件处理的所谓消费(consume)概念即可,一个用户的操作会被传递到不同的View控件和同一个控件的不同监听方法处理,任何一个接收并处理了该次事件的方法如果在处理完后返回了true,那么该次event就算被完全处理了,其他的View或者监听方法就不会再有机会处理该event了。

     onLongClick的发生是由单独的线程完成的,一般发生在ACTION_UP之前,而onClick的发生是在ACTION_UP后。临界条件是同时发生,这里会有flag来进行区分。

因此同一次用户touch操作就有可能既发生onLongClick又发生onClick。

及时向系统表示“我已经完全处理(消费)了用户的此次操作”,是很重要的事情。

另外一个同时执行的概念(都执行的意思),先后执行,例如,我们如果在onLongClick()方法的最后return true,那么onClick事件就没有机会被触发了。

 

在onLongClick()方法return false的情况下,一次触碰操作的基本时序:

04-05 06:00:53.023: DEBUG/TSActivity(277): onTouch ACTION_DOWN

04-05 06:00:53.533: DEBUG/TSActivity(277): onLongClick 

04-05 06:00:55.603: DEBUG/TSActivity(277): onTouch ACTION_UP

04-05 06:00:55.663: DEBUG/TSActivity(277): onClick

可以看到,在ACTION_UP后仍然触发了onClick()方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值